Systems
Async Queue#
This sample shows how to load resources like meshes and textures in the background using the AsyncQueue class. Files are loaded in a separate thread, so the main application stays responsive.
Meshes and textures are added to the loading queue, and the system listens for events to know when each resource is ready. When a mesh finishes loading, it's removed from the queue. For textures, an event handler is used to handle their completion. The sample also demonstrates how to group and manage resource requests, making it easier to control the loading process.
This kind of async loading is useful for streaming large levels, loading assets on demand in VR, or preloading data in simulations without freezing the interface.
SDK Path: <SDK_INSTALLATION>source/systems/async_queue
Cad-Like View#
This sample demonstrates how to build a CAD-style layout by combining four synchronized views of the same scene: top, side, front, and perspective. Each view uses its own camera with a separate projection matrix - orthographic for technical views and perspective for the main one. Each view is rendered off-screen and displayed through a WidgetSpriteViewport.
The views are arranged in a 2x2 grid using GUI widgets. When the window is resized, texture resolutions are automatically updated to match the new layout and keep the viewports sharp.
Viewcubes are centered on the main object to maintain consistency across all views. They help indicate camera orientation and are updated based on the window size and viewport positions.
This setup is ideal for tools that require accurate inspection of a scene from multiple directions, such as modeling, level design, or CAD-style applications.
SDK Path: <SDK_INSTALLATION>source/systems/cad_like_view
Callbacks#
This sample demonstrates how to use the CallbackBase class via the C++ API to wrap and call functions and class methods with various numbers of arguments.
Callbacks are created using the MakeCallback method for both standalone functions and member methods, including parameterized versions with up to four arguments. Once created, callbacks can be executed using CallbackBase::run() method, optionally passing different arguments at runtime. This allows storing and triggering functions dynamically through a unified interface.
Callback mechanism is useful in scenarios such as event-driven systems, user interface interactions, or asynchronous task management in applications requiring dynamic function invocation.
SDK Path: <SDK_INSTALLATION>source/systems/callbacks
Console#
This sample demonstrates how to interact with the engine's built-in console and add custom console commands and variables via API using the Console and ConsoleVariable classes.
It shows how to define different types of console variables: ConsoleVariableInt, ConsoleVariableFloat, and ConsoleVariableString, and how to register custom console commands. Commands are linked to callback functions using MakeCallback, and can be executed directly from code or entered manually through the console.
Commands can also be added and removed dynamically at runtime, making the system flexible for various use cases. Console variables can be accessed or changed through both code and the console interface.
This can be used for development, debugging, rapid prototyping, and runtime adjustments in interactive applications.
SDK Path: <SDK_INSTALLATION>source/systems/console
CPU Shader#
This sample demonstrates how to implement a custom CPU shader by inheriting from the CPUShader class to perform multi-threaded data processing outside the main rendering loop.
The system updates multiple ObjectMeshCluster instances asynchronously by using a helper AsyncCluster structure. Each cluster maintains two versions of itself: one for rendering and one for background updates. At the end of each frame, the two are swapped so the visible cluster always shows the latest result without stalling the frame.
The parallel logic is encapsulated in a derived shader class UpdateClusterCPUShader, where the process() method is overridden to perform per-cluster updates. This method is automatically dispatched using CPUShader::runAsync(), allowing the workload to be spread across available CPU threads. Swap operations, visibility checks, and update decisions are handled independently for each cluster.
This approach is particularly effective for real-time procedural animation, large-scale mesh updates, or any CPU-side logic that benefits from multithreading while remaining synchronized with rendering.
SDK Path: <SDK_INSTALLATION>source/systems/cpu_shader
Events#
This sample demonstrates four different patterns for subscribing UNIGINE's Events via the C++ API, highlighting how event handler lifetime and management can vary depending on the approach.
Each method demonstrates a different strategy for connecting to the same event and managing event handler lifetimes:
- EventConnectionExample stores a single event handler with manual control over its activation. This type of connection is useful when you need precise control — you can enable, disable, or fully disconnect the handler at any time.
- EventConnectionsExample acts as a container for multiple handlers. It handles cleanup automatically (via the destructor) and manually (by calling EventConnections::disconnectAll()). This is useful when you have many event handlers with varying lifetimes that need to be grouped.
- InheritedEventConnectionExample inherits EventConnections class, making connection management part of its internal logic. All connected handlers are automatically disconnected when the object is destroyed.
- CallbackIDConnection provides a low-level, manual way to manage handlers using a connection ID. It offers flexibility but requires careful memory and lifetime handling. This approach is considered unsafe and should only be used when you fully understand the implications.
Each example connects to a shared EventHolder, and handlers are triggered with a sample value. This setup is useful when designing modular, reactive systems that rely on flexible and explicit event-driven logic.
SDK Path: <SDK_INSTALLATION>source/systems/events
Events Advanced#
This sample demonstrates advanced usage of the UNIGINE event system.
EventsAdvancedSample.cpp triggers custom rotation events when specific keys are pressed. Each event passes one or more arguments to connected listeners.
EventsAdvancedUnit.cpp shows how to connect various types of handlers, including:
- Class methods with extra arguments
- Free functions with discarded or additional arguments
- Lambdas using connectUnsafe()
- Storing connections using EventConnection or EventConnectionId for later disconnection
This sample helps understand flexible patterns for event handling in modular component systems.
SDK Path: <SDK_INSTALLATION>source/systems/events_advanced
External Package#
This sample demonstrates how to create a custom data package using code and use it to generate objects in the scene.
Package is a collection of files and data for UNIGINE projects stored a single file. The Package class is a data provider for the File System. You can use it to load all necessary resources.
The ExternalPackage class describes the generation of a mesh (in this case, a box) and its saving to a temporary file at a specified path. The class also implements an interface for searching, reading, and retrieving information about files within the package.
The ExternalPackageSample class adds the created external package, and its contents are used to create meshes with different positions and orientations. This approach allows for quick and convenient management of a large number of objects without adding them by hand.
Packages can be used to conveniently transfer files between your projects or exchange data with other users, be it content (a single model or a scene with a set of objects driven by logic implemented via C# components) or files (plugins, libraries, execution files, etc.).
Using this example will help you understand how to organize work with external files, create and manage your own data packages, implement a mechanism for loading and reading data from a package.
SDK Path: <SDK_INSTALLATION>source/systems/external_package
Ffp#
This sample demonstrates how to render a simple 2D shape using the Fixed Function Pipeline (Ffp) in UNIGINE via the C++ API. A colorful figure composed of 16 vertices is drawn directly on screen using orthographic projection.
The rendering logic is called every frame by hooking into the engine's render loop. Ffp mode is enabled for drawing and then disabled, keeping this rendering isolated from the rest of the frame.
This approach is useful for quick visualization overlays, editor tools, or debugging tasks where shader-based rendering isn't required.
SDK Path: <SDK_INSTALLATION>source/systems/ffp
File#
This sample shows how you can create a text file and display its contents inside the widget via C++ API by using the File class. To create a text file, type the text from keyboard inside the Writer widget and press Write to save. Click Read inside the Reader widget to display the recorded information. The saved information will be displayed in the same widgets when you start the sample next time.
SDK Path: <SDK_INSTALLATION>source/systems/files
Images#
This sample shows how to procedurally generate 3D image data and use it as a density texture for a volume-based material in real time.
The result is visualized using a volume box that updates dynamically every frame based on custom field simulation.
The sample initializes a 3D image with a predefined resolution and fills it with voxel data derived from a set of moving fields. Each field represents an abstract spherical influence zone that contributes to the voxel density based on distance. Field dynamics are updated every frame to simulate motion.
The raw image data is accessed directly via a pixel pointer and modified per frame, with density values mapped to RGBA channels. The resulting image is then uploaded to a material as a 3D texture used in a volumetric shading model.
The sample demonstrates how to work with the Image class and update GPU resources efficiently at runtime. This approach can be used for generating volumetric effects such as clouds, fog, or procedurally driven visual phenomena.
SDK Path: <SDK_INSTALLATION>source/systems/images
Multiple Async Requests#
This sample demonstrates how to launch and manage a large number of asynchronous ray-based intersection queries simultaneously.
The results are visualized in real time and latency statistics are displayed for performance analysis.
In this sample, an emitter object continuously rotates and moves vertically, casting rays in multiple directions (slices and stacks) to detect intersections with objects in the world. Each ray is handled asynchronously.
All active requests are monitored for completion. Once finished, the results (intersection points and normals) are visualized using Visualizer tools. A latency histogram is computed based on how many frames passed between the request and response, and the results are displayed in the UI.
The sample uses double-buffering for safe multi-threaded access and demonstrates efficient scheduling of a high number of asynchronous operations. This approach is useful for stress-testing intersection systems, profiling async request latency, or building interactive tools relying on high-frequency spatial queries.
SDK Path: <SDK_INSTALLATION>source/systems/intersection_multiple_async_requests
Simple Async Requests#
This sample demonstrates how to perform a single asynchronous intersection query based on the user's mouse cursor position in the scene. The result includes the hit point and surface normal, which are visualized in the scene, along with latency information.
The sample demonstrates detection of intersections with all objects in the world using a combination of World::getIntersection() and Landscape::getIntersection() methods. A single ray is cast from the current camera position through the mouse cursor. If the ray intersects with any geometry, the hit point and surface normal are rendered using Visualizer. Intersection queries are handled asynchronously. A callback processes the result and records latency in frames. The average and maximum latency values are updated in real time and shown in the sample UI.
This setup demonstrates how to implement non-blocking intersection queries suitable for object selection or similar real-time input-driven interactions.
SDK Path: <SDK_INSTALLATION>source/systems/intersection_simple_async_request
JSON#
This sample shows how to generate a structured JSON document containing objects, arrays, and various data types such as strings, numbers, booleans, and null values. It also demonstrates how to traverse and print this structure recursively with indentation, imitating a pretty-printed output.
The sample begins by constructing a custom JSON structure in memory using Json::create() and its child manipulation methods. Nodes are added dynamically and include both named and unnamed children of various types. Once built, the structure is traversed recursively and printed to the console in a readable format using indentation and commas, based on node type and position. The code demonstrates how to distinguish between arrays, objects, and primitive values when printing.
This sample is useful for learning the basics of JSON manipulation, such as creating structured data, traversing an element tree, and formatting output. It can serve as a foundation for processing JSON data (e.g., responses to REST API requests), as well as for complex serialization or debugging tools.
SDK Path: <SDK_INSTALLATION>source/systems/json
Materials and Properties#
This sample demonstrates how to access all materials and properties in the project via API.
The sample iterates through the list of registered in the Property Manager via Properties::getProperty() and prints out the names and child counts for each. It also gets all available materials from the Materials Manager via Materials::getMaterial(), and lists them along with their file paths and number of children.
This can be used as a reference for accessing and working with project assets at runtime - whether for inspection, dynamic assignment, or content management logic.
SDK Path: <SDK_INSTALLATION>source/systems/materials_and_properties
Microprofiler#
This sample demonstrates methods for tracking performance and estimating the time spent on different sections of code. For this purpose, it uses Microprofile, an advanced CPU/GPU profiler with per-frame inspection support.
Profiling is crucial for identifying performance bottlenecks and optimizing code execution. This analysis helps you understand if any code sections negatively impact the project's speed.
SDK Path: <SDK_INSTALLATION>source/systems/microprofiler
Mount Points#
This sample demonstrates the functionality of mount points in the Engine file system.
MountPointsSample.cpp allows you to add or remove mount points for a folder and a package archive via API. If the mount point is active, an image stored inside will be loaded and displayed.
Mounted paths are shown in the UI window, where you can toggle between mounting or unmounting each resource. Images are accessed using virtual paths defined by the mount location.
The sample illustrates the concept of virtualized file access: if a resource is not available via a mount point, it will not be found or displayed by the Engine.
This approach is useful for working with external content (stored outside the data folder), modular data loading, or switching asset sets at runtime.
SDK Path: <SDK_INSTALLATION>source/systems/mount_points
Stream Base#
This sample demonstrates how to create a custom stream class by inheriting from StreamBase and use it for reading from and writing to files. The resulting stream is used to serialize and deserialize basic data types to and from a binary file.
The sample provides a wrapper around standard C file I/O functions and integrates with the UNIGINE stream system by implementing the StreamBase interface. In the sample logic, a binary file is first created and filled with data via Stream::writeString(), writeInt(), and writeFloat(). Then the file is reopened in read mode and the same values are read back using the corresponding Stream 'read' methods, verifying the functionality of the custom stream.
This example serves as a reference for implementing custom stream sources (e.g., from memory, network, or virtual filesystems) and integrating them with the engine's serialization tools.
SDK Path: <SDK_INSTALLATION>source/systems/stream_base
Thread#
This sample shows how to define and manage background threads in UNIGINE by inheriting from the Thread class and overriding the process() method.
Two custom thread types are demonstrated:
- InfiniteThread - continuously outputs messages while running.
- CountedThread - performs a finite number of iterations before completing.
Threads are started during component initialization and executed in parallel with the main engine loop. The infinite thread is explicitly stopped via stop() once the counted thread completes all iterations.
This sample illustrates basic principles of multithreading and can serve as a foundation for offloading computations or I/O operations from the main thread.
SDK Path: <SDK_INSTALLATION>source/systems/thread
Two-Point Perspective#
This sample shows how to simulate a two-point perspective projection using a lens shift technique implemented via a secondary Dummy Player. When enabled, the sample dynamically adjusts the projection matrix of a dummy camera to visually align vertical lines while preserving the viewing direction.
The effect is achieved by adjusting the projection matrix of a PlayerDummy instance according to the pitch angle of the active camera. During the rendering phase, the Dummy Player temporarily replaces the main camera to apply the modified view.
This approach can be used for architectural visualization or stylized camera effects where a more orthographic-like vertical perspective is desired.
SDK Path: <SDK_INSTALLATION>source/systems/two_point_perspective
USC Arrays#
This sample showcases integration between C++ and UnigineScript by registering external C++ functions that manipulate UnigineScript array types.
The registered functions allow for setting and getting values, generating test data, and enumerating the contents of both ArrayVector (indexed container) and ArrayMap (associative container).
SDK Path: <SDK_INSTALLATION>source/systems/usc_arrays
USC Callbacks#
This sample demonstrates how to call UnigineScript functions from C++ code via callbacks.
The mechanism is based on Variable Class instances and allows calling both custom and built-in script functions by name.
The sample registers a C++ wrapper function to expose script invocation capability to UnigineScript via the Interpreter class.
SDK Path: <SDK_INSTALLATION>source/systems/usc_callbacks
USC Classes#
This sample demonstrates how to export classes from C++ side to UnigineScript.
A simple C++ class named ExternClass is used to export custom MyExternObject into the UnigineScript environment. This allows scripts to instantiate the class, call its methods, and interact with its properties at runtime.
SDK Path: <SDK_INSTALLATION>source/systems/usc_classes
USC Functions#
This sample demonstrates how to export functions from C++ side to UnigineScript. It includes examples of exporting regular functions, handling multiple data types, and registering class members for a singleton-like object.
SDK Path: <SDK_INSTALLATION>source/systems/usc_functions
USC Inheritance#
This sample demonstrates how to work with UnigineScript containers via C++ API. It showcases class composition, constructor registration, base-to-derived linkage, and virtual method exposure within a scripting context.
Each class in the hierarchy is registered via the Interpreter class, allowing scripts to instantiate and interact with derived types, call inherited methods, and override behavior.
SDK Path: <SDK_INSTALLATION>source/systems/usc_inheritance
USC Stack#
This sample demonstrates how to use a stack implemented via C++ in UnigineScript.
The sample defines a simple formatter function on the C++ side. This function takes a format string and substitutes tokens with values popped from a runtime stack. Values are passed from the script and pushed onto the stack prior to the call.
SDK Path: <SDK_INSTALLATION>source/systems/usc_stack
USC Structures#
This sample demonstrates how to expose C++ structs to UnigineScript using the Interpreter class.
It defines a simple C++ structure MyVector with four float fields (x, y, z, w) and registers it. Each field is mapped via explicit getter and setter methods to allow full read/write access from the UnigineScript side.
SDK Path: <SDK_INSTALLATION>source/systems/usc_structures
USC Transfer#
This sample demonstrates how to transfer complex data between UnigineScript and C++ using the Variable class and the TypeToVariable utility.
The example shows several ways to pass and return Image objects between script and native code. It compares direct object passing, conversion via Variable, and using TypeToVariable.
SDK Path: <SDK_INSTALLATION>source/systems/usc_transfer
USC Types#
This sample demonstrates how to enable type conversion between custom C++ types and UnigineScript using the Variable class.
A user-defined MyVector3 class is introduced to represent a 3D vector. To integrate this class with the UnigineScript environment, custom specializations of the TypeToVariable and VariableToType templates are implemented. These allow automatic conversion between MyVector3 and vec3 values inside the UnigineScript runtime.
SDK Path: <SDK_INSTALLATION>source/systems/usc_types
USC Variables#
This sample demonstrates how to work with different variable types in UnigineScript using the Variable class from C++ code.
Various types (int, long, float, double), and vector types (vec3, vec4, dvec3, etc.), are wrapped in Variable objects and passed into a UnigineScript callback function.
SDK Path: <SDK_INSTALLATION>source/systems/usc_variable
Visualizer#
This sample demonstrates the full range of features provided by the Visualizer class for visual debugging.
The sample illustrates how to use Visualizer for debugging node positions, physics vectors, bounding volumes, and custom geometry in both world space and screen space. Use controls to explore the area.
VisualizerUsage.cpp renders a wide range of primitives including points, lines, boxes, frustums, spheres, capsules, and object bounds using Visualizer methods.
2D visualizer features can be toggled on and off via the corresponding checkboxes.
Enable or disable depth testing, toggle specific primitives, and inspect how different rendering options behave in real time.
SDK Path: <SDK_INSTALLATION>source/systems/visualizer
Xml#
This sample demonstrates how to create and manipulate an XML document using the Xml class.
The sample creates a nested XML tree with multiple child nodes, each containing arguments and optionally a text value. The structure is built using the Xml::addChild() method, and the arguments are parsed using Xml::getArgName() and Xml::getArgValue(). After construction, the XML tree is traversed recursively to display the structure and all attributes in the console output.
This approach demonstrates the use of the Xml class for working with hierarchical data, which is useful for config files, level data, and other structured content in XML format.
SDK Path: <SDK_INSTALLATION>source/systems/xml
The information on this page is valid for UNIGINE 2.20 SDK.