Adding Scripts to the Project
Starting coding your project is simple with the use of UnigineScript language (no compilation is required).
For this tutorial we are going to get a primitive object (a box) from a script and add game logic to rotate it.
Step 1. Add The Primitive Object To The World
- Run the project with the loaded editor via the SDK Browser.
- On the Menu bar, choose Create -> Primitive -> Box to create a box object.
- In Create Box window that opens, specify the size of the box and click Ok.
- Click the left mouse button to place the box.
- On the Menu bar, click Windows -> Nodes or press N to open the Nodes window.
- Choose added node and rename it to box. Change the position to 0, 0, 1.
- On the Menu bar, click File -> Save world or press CTRL + S to save the world.
Step 2. Add Script Logic
There are two methods to add script to the object:
1 Method: By Editing the .cpp World Script File
To add logic that will rotate the box, you should modify the <your_project_name>.cpp world script file in a plain text editor.
- Open the project folder via the SDK Browser.
-
Open <your_project_name>.cpp script file located in your data/<your_project_name> folder by using plain text editor.
#include <core/unigine.h> int init() { PlayerSpectator camera = new PlayerSpectator(); camera.setPosition(Vec3(2.0f,0.0f,1.5f)); camera.setDirection(Vec3(-1.0f,0.0f,-0.5f)); engine.game.setPlayer(camera); return 1; } int shutdown() { return 1; } int update() { return 1; }
The world script contains the following functions by default:
- init() function is used to create objects and initialize all other necessary resources on the world load.
- update() function is used to code project logic and executed every frame.
- shutdown() function is used to code project logic and executed when the world is unloaded.
This part of init() function code creates a new free-flying game camera that collides with objects (but does not push or interact with them). Read more about engine functions.
// create a new spectator player PlayerSpectator camera = new PlayerSpectator(); // turn it in the specified direction camera.setPosition(Vec3(2.0f,0.0f,1.5f)); // place it in the specified point camera.setDirection(Vec3(-1.0f,0.0f,-0.5f)); // set the player as default one engine.game.setPlayer(camera);
Comments were added to explain to you the meaning of each line of code. - Add a variable to handle the required box node before the init() function.
We do NOT recommend you to create global variables for the real project.
Node box; // add a box node int init() { /* ... */ }
- Put this code into the init() function to get the box node.
Node box; // add a box node int init() { /* ... */ // search the node by the specified name int index = engine.editor.findNode("box"); // get the node by its index if(index != -1) { box = engine.editor.getNode(index); } return 1; }
Though nodes can be handled by any of the scripts (world, system or editor one) and Unigine Engine Editor (that loads and stores all the nodes from the world file), they should be owned only by one of them. Otherwise, such nodes can cause engine crash or memory leak problems.
See Memory Management article for details. - Set the node transformation in the update() loop. Note that it is necessary to scale the rotation angle each frame with the frame duration (because it's different for each individual frame) to get constant angular velocity. Thus, the resulting script is:
/* ... */ int update() { // check whether the node exists if(box != NULL) { // get the frame duration float ifps = engine.game.getIFps(); // set the angle of rotation float angle = ifps * 90.0f; // get the current transformation of the node and apply rotation mat4 transform = box.getTransform() * rotateZ(angle); // set new transformation to the node box.setTransform(transform); } return 1; }
#include <core/unigine.h> Node box; // add a box node int init() { // create a new spectator player PlayerSpectator player = new PlayerSpectator(); // place it in the specified point player.setPosition(vec3(3.5,0.0,1.3)); // turn it in the specified direction player.setDirection(vec3(-1.0,0.0,-0.3)); // set the player as default one engine.game.setPlayer(player); // search the node by the specified name int index = engine.editor.findNode("box"); // get the node by its index if(index != -1) { box = engine.editor.getNode(index); } return 1; } int shutdown() { return 1; } int update() { // check whether the node exists if(box != NULL) { // get the frame duration float ifps = engine.game.getIFps(); // set the angle of rotation float angle = ifps * 90.0f; // get the current transformation of the node and calculate rotation mat4 transform = box.getTransform() * rotateZ(angle); // set new transformation to the node box.setTransform(transform); } return 1; }
- Save all the changes in the <your_project_name>.cpp world script file.
- If you have already opened your project, open console by pressing the grave accent (`) key, placed under the ESC key.
- Type the command and press Enter to see the result.
world_reload
2 Method: By Using WorldExpression Objects
You can add the script to the box by using the WorldExpression object.
- On the Menu bar, choose Create -> World -> Expression to create the WorldExpression object.
- Click the left mouse button to place the box.
- On the Menu bar, click Windows -> Nodes or press N to open the Nodes window.
- Choose the added WorldExpression node and change the position to 1, -1, 0.5. Now you have the primitive box and the World Expression object on a plane.
- Choose the WorldExpression node and open the Expression tab.
- Put code into the Source field.
{ // get the WorldExpression node via its internal function Node worldExpression = getNode(); // get the frame duration float ifps = engine.game.getIFps(); // set the angle of rotation float angle = ifps * 90.0f; // get the current transformation of the node and apply rotation mat4 transform = worldExpression.getTransform() * rotateZ(angle); // set new transformation to the node worldExpression.setTransform(transform); }
Curly braces are mandatory!Other ways of attaching scripts to the World Expression object you can read here.
- Drag the box node with ALT button pressed to the worldExpression node in the Nodes hierarchy list.
If the box node gets outside the viewing frustum, but the bounding box is still in the viewing frustum or the camera is inside this bounding box, the playback of the transformation sequence will continue.All the objects that are children of the World Expression object inherit expression transformations.
- Close the Nodes window to see the result.