Language Features
Dynamic Typing
Unlike C++ using Static Typing, UnigineScript is using Dynamical Typing, which means that type checking is performed during execution but not during variable declaration. According to this fact, you may face following situations:
- Though in many parts of documentation you can see variables declared with specific types or function arguments of specific types, these type markers are simply hints to the user. That is, you can define an int variable and assign a string to it.
- The interpreter will not do type checking for you before it starts evaluating an expression. If you need data of a specific type or a specific custom class, use the typeof() and typeinfo() functions to check it.
- From time to time you will see a variable type in function declarations. variable is not actually a type, and this word is not even reserved. The variable pseudo-type simply means that a function "knows" that it can accept data of different types and will act differently depending on the type of the variable argument.
- Still, there are several base types, which names are reserved, and we will briefly examine them here. Also, you can define your own types—classes.
Memory Management
UnigineScript provides a garbage collector that automatically manages memory for objects created in UnigineScript: allocates it when needed and frees it, when no object references it any more. The garbage collector is launched once per several frames. For all allocated memory chunks, it checks, if any reference to them still exists; if a chunk is not referenced by any object, it is freed. Also, all allocated memory is freed, when the script quits.
See also: Destructors and delete
Serialization
Unigine serialization mechanism allows saving a state of an object into a binary file and later restoring it. Pure-UnigineScript classes are saved and restored automatically, without any effort of the programmer. However, if the class uses objects exported from C++, which do not implement serialization themselves, two special methods should be defined:
- __save__()
- __restore__()
class Foo {
// Foo.__save__() will be called before saving the state of the virtual machine
void __save__() {
save_to_file(“file.xml”);
}
// Foo.__restore__() will be called after restoring the state of the virtual machine
void __restore__() {
load_from_file(“file.xml”);
}
// save to file
void save to file(string filename) {
// …
log.message(“saving\n”);
}
save to file
void load_from_file(string filename) {
// …
log.message(“loading\n”);
}
};
engine.console.run(“state_save”);
See also: Serialization in Unigine C++ API.
Syntactical Differences between C++ and UnigineScript
Here is a list of main syntactical differences between the two languages.
- Vector initialization is different from C++. Instead of providing a list of vector items inside two curly braces, enclose the items in simple parentheses.
- Constructors defined separately from the class declaration have a different signature, see Constructors and new .
- Destructors defined separately from the class declaration have a different signature, see Desctructors and delete .
- Members are always accessed using the dot operator.
- There is no protected access level modifier, there are only public and private ones. All class members are public by default.
-
UnigineScript uses namespaces, which represent function libraries. Namespace names and function names are separated using the dot operator. Note that a namespace name can also contain dots, so, to avoid ambiguity, only the last dot is used as a separator between the namespace and the function.
There are also "ordinary" namespaces that specify a scope of variables and functions.
- Objects of vector data types allow accessing their members using swizzling, that is, if you have an object my_vector of type vec3, you can access its members like this: my_vector.x, my_vector.zyx, etc.
- UnigineScript does not support structures (struct).
- UnigineScript provides a number of additional statements that affect control flow: forloop , foreach , foreachkey , yield , wait .
- There is a special function named call in UnigineScript. This function evaluates any function, which name is passed to it as an argument.
- There is no "virtual" keyword in UnigineScript. When a user class is inherited from another class, both automatically support virtual methods.