This page has been translated automatically.
Video Tutorials
Interface
Essentials
Advanced
How To
Rendering
Professional (SIM)
UnigineEditor
Interface Overview
Assets Workflow
Version Control
Settings and Preferences
Working With Projects
Adjusting Node Parameters
Setting Up Materials
Setting Up Properties
Lighting
Sandworm
Using Editor Tools for Specific Tasks
Extending Editor Functionality
Built-in Node Types
Nodes
Objects
Effects
Decals
Light Sources
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
Programming
Setting Up Development Environment
Usage Examples
C++
C#
UnigineScript
UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
Materials and Shaders
Rebuilding the Engine Tools
GUI
Double Precision Coordinates
API
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
Content Creation
Content Optimization
Materials
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials

Where to Put Your Code

The world logic has a number of functions that are used to code logic of the application. Initialization function of the world logic (init()) is used to create objects and initialize all other necessary resources on the world load. Shutdown function (shutdown()) is called when the world is unloaded and is used to delete resources that were created during the logic execution to avoid memory leaks.

But what about the frame-by-frame update? In the world logic, this update is performed within the main loop that has the following blocks for that:

  • updateAsyncThread() can contain logic functions to be called every frame independently of the rendering thread: pathfinding, generation of procedural textures, custom physics, etc.
  • updateSyncThread() can contain any parallel logic functions to be executed before update().
  • update() can contain any logic: control what to render on the screen and how to do it, render to textures, create nodes, call console commands, etc.
  • updatePhysics() can be used to simulate physics: perform continuous operations (pushing a car forward depending on current motor's RPM, simulating a wind blowing constantly, perform immediate collision response, etc.).
  • postUpdate() can be used to correct behavior according to the updated node states in the same frame.
  • swap() can be used to process the results of the updateAsyncThread() function.

Code UpdateAsyncThread()#

In the world logic updateAsyncThread(), you can specify all logic functions you want to be called every frame independently of the rendering thread. This function can be used to perform some heavy resource-consuming calculations performed during the whole frame, such as pathfinding, generation of procedural textures, custom physics, and so on. This function does not block the main thread.

Code UpdateSyncThread()#

In the world logic updateSyncThread(), you can specify any parallel logic functions you want to be executed before update(). This function blocks the Main Thread until all calls are completed.

This function can be used to perform some heavy resource-consuming calculations such as pathfinding, generation of procedural textures, manipulations with big amounts of data, the result of which is required before the frame starts to be rendered. This function can also be used for simpler operations, that can be implemented in the update() function, to distribute between threads and improve performance.

Code Update()#

In the world logic update(), you can put all functions to be called every frame, while your application is executed. It serves for implementing any logic. In brief, you can control a lot of things (whether graphics-related or not) from within the update(). Here you can:

Notice
Do not apply forces and torques to rigid bodies in the update(). Otherwise, you will get an unstable result that varies with each rendering frame. All continuous operations must be within updatePhysics().

World Event Handlers#

Event handlers set in update() (for example, by using WorldTrigger or widget event handlers) are not executed immediately. They are run when the next engine function is called: that is, before updatePhysics(), if any (in the current frame), or before the next update() (in the following frame) — whatever comes first.

Code UpdatePhysics()#

The updatePhysics() function of the world logic is mainly used to control physics in your application. As a rule this function is used for continuous operations such as pushing a car forward depending on current motor's RPM, simulating a wind blowing constantly, performing immediate collision response (as updatePhysics() can be executed several times during a single rendering frame, you can process multiple bounces of objects, when they collide with each other and monitor them, while the update() will only show us the final result), etc. The updatePhysics() is executed in the Main thread, so you can perform any actions here just like in the update():

You can as well do the following (and a lot more):

  • Reposition and transform nodes if they are enabled.
  • Create new nodes.
  • Delete nodes.

Physics Event Handlers#

By default in Async Rendering physics mode, if you set any physics-based event handlers in updatePhysics() or use a PhysicalTrigger, they cannot be executed immediately, as the rendering process is already in action and they can violate it. If there is one more physics iteration to go, these event handlers or a PhysicalTrigger are executed before the next updatePhysics(); if not, before the next world logic update().

You can safely reposition or transform, create or delete nodes in your physics event handler functions, as they are executed in the Main thread.

Code PostUpdate()#

The postUpdate() function of the world logic is an additional function used to correct behavior after the state of the node has been updated (for example, skinned animation has been played in the current frame or particle system has spawn its particles).

Imagine a situation when we need to attach an object (let's say, a sword) to the hand of a skinned mesh character. If we get transformation of the character hand bone and set it to the sword in the update() function, the attachment will be loose rather than precise. The sword will not be tightly held in the hand, because the animation is actually played right after the world logic update() has been executed. This means, returned bone transformations in the update() will be for the previous frame. The world logic postUpdate() is executed after animation is played, which means you can get updated bone transformations for the current frame from within this function and set them to the sword.

Notice
Use postUpdate() for correction purposes only; otherwise, this will increase the main loop time. All other functions should be placed within update() or updatePhysics() (physics).

Code Swap()#

Engine calls this function after the following processes are completed: rendering (CPU portion), physics calculations and pathfinding, GUI rendering, and all Async threads. The function is designed to process the results of the updateAsyncThread() method — all other methods (threads) have already been performed and are idle. After this function, only two actions occur:

  • All objects that are queued for deletion are deleted.
  • Profiler is updated.

Last update: 2024-02-06
Build: ()