Programming
Fundamentials
Setting Up Development Environment
UnigineScript
High-Level Systems
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine and Tools
GUI
Double Precision Coordinates
API
Core Library
Containers
Engine Classes
Node-Related Classes
Rendering-Related Classes
Physics-Related Classes
Bounds-Related Classes
GUI-Related Classes
Controls-Related Classes
Pathfinding-Related Classes
Utility Classes

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.

Notice
Objects exported from the C++ part exist until the explicit call of their destructors. See also information on memory management for Extern classes.

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__()
Names of these methods are reserved; think of them as an interface that should be implemented to perform object serialization. The first method, __save__(), is called before the virtual machine state is saved. The second method, __restore__(), is called after the virtual machine state is restored.
Notice
You can either define a pair of __save__() and __restore__() without arguments, or a pair of __save__(Stream) and __restore__(Stream). But you cannot mix between the two pairs. There is no need to define both pairs, as in this case, the functions which take the Stream argument will be called.
Source code(UnigineScript)
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.

  1. Vector initialization is different from C++. Instead of providing a list of vector items inside two curly braces, enclose the items in simple parentheses.
  2. Constructors defined separately from the class declaration have a different signature, see Constructors and new .
  3. Destructors defined separately from the class declaration have a different signature, see Desctructors and delete .
  4. Members are always accessed using the dot operator.
  5. There is no protected access level modifier, there are only public and private ones. All class members are public by default.
  6. 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.
    Notice
    There are also "ordinary" namespaces that specify a scope of variables and functions.
  7. 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.
  8. UnigineScript does not support structures (struct).
  9. UnigineScript provides a number of additional statements that affect control flow: forloop , foreach , foreachkey , yield , wait .
  10. There is a special function named call in UnigineScript. This function evaluates any function, which name or identifier is passed to it as an argument.
  11. There is no "virtual" keyword in UnigineScript. When a user class is inherited from another class, both automatically support virtual methods.
Last update: 2017-07-03