Доступ к нодам и файлам через свойства (Property)
Every resource (asset) used in your project, be it a node, a mesh, a material, a texture, or any other, has a unique identifier (GUID). A GUID identifies a path to the asset (i.e., location of the asset in the project). GUIDs are used to keep all links and dependencies between the assets, regardless of their name and location within the project (when you change asset's name or location within the project, its GUID does not change).Каждый ассет ( asset), используемый в вашем проекте, будь то нода, меш, материал, текстура или любой другой, имеет уникальный идентификатор (GUID). Идентификатор GUID определяет путь к ассету (т.е. местоположение ассета в проекте). Идентификаторы GUID используются для сохранения всех связей и зависимостей между ассетами, независимо от их имени и местоположения в проекте (при изменении имени или местоположения ассета в проекте его идентификатор GUID не изменяется).
Using GUIDs to link your assets is safer than using file names, as you don't have to worry that your material will lose a texture when you change its name. However, managing GUIDs directly is rather confusing.Использование идентификаторов GUID для связывания ваших ассетов безопаснее, чем использование имен файлов, поскольку вам не нужно беспокоиться о том, что ваш материал потеряет текстуру при изменении его имени. Однако прямое управление идентификаторами GUID довольно запутанно.
Property allows linking certain assets to a node via GUIDs without even thinking about them, giving you easy access to these assets. There is a number of property parameter types making that possible:Свойство позволяет привязывать определенные ассеты к ноде с помощью GUID, даже не задумываясь о них, предоставляя вам легкий доступ к этим ассетам. Существует ряд типов параметров свойств, делающих это возможным:
- material - for materialsmaterial - для материалов
- property - for propertiesproperty - для свойств
- file - for all other files (textures, meshes, sounds, etc.)file - для всех остальных файлов (текстур, сеток, звуков и т.д.)
The node property parameter type allows linking a node to another node in a similar way using the ID.Тип параметра свойства node позволяет связать одну ноду с другой аналогичным образом, используя идентификатор.
Artists and programmers developing a project should be able to work independently: artists prepare content (textures, materials, models etc.), while programmers write code implementing logic that performs certain operations with the content.Художники и программисты, разрабатывающие проект, должны иметь возможность работать независимо: художники готовят контент (текстуры, материалы, модели и т.д.), в то время как программисты пишут код, реализующий логику, которая выполняет определенные операции с контентом.
Using properties makes the whole process simpler:Использование свойств упрощает весь процесс:
- Artists can safely move or rename files and nodes. Programmers always work with properties: create them, set and read parameter values (which can represent links to various assets). Artists can set property parameters too, they do it via the Editor.Художники могут безопасно перемещать или переименовывать файлы и ноды. Программисты всегда работают со свойствами: создают их, устанавливают и считывают значения параметров (которые могут представлять ссылки на различные ассеты). Художники тоже могут устанавливать параметры свойств, они делают это через редактор.
- Neither artists nor programmers should work with node IDs or GUIDs and remember them. A programmer always has at hand a variable (property parameter) that gives access to any necessary node or a file.Ни художники, ни программисты не должны работать с идентификаторами нод или идентификаторами GUID и запоминать их. Программист всегда имеет под рукой переменную (параметр свойства), обеспечивающую доступ к любой необходимой ноде или файлу.
General property-based workflow is clear and simple. There are two basic cases, depending on the logic of your project:Общий подход, основанный на свойствах, понятен и прост. Существует два основных случая, в зависимости от логики вашего проекта:
General WorkflowОбщий подход#
The general workflow for all projects that don't use the C++ Component System should be as follows:Общий подход для всех проектов, которые не используют Систему компонентов C++, должен быть следующим:
-
First, we create a property to store links to all nodes and assets that we need and save it to our project's data folder. For example, the property can be like this: Сначала мы создаем свойство для хранения ссылок на все ноды и ассеты, которые нам нужны, и сохраняем его в папке data нашего проекта. Например, свойство может быть таким:
<?xml version="1.0" encoding="utf-8"?> <property version="2.16.0.2" name="my_property" parent_name="node_base" manual="1"> <parameter name="some_float" type="float">30.5</parameter> <parameter name="some_string" type="string">Hello from my_property!</parameter> <parameter name="some_node" type="node">0</parameter> <parameter name="some_material" type="material"></parameter> <parameter name="some_mesh" type="file"></parameter> <parameter name="some_file" type="file"></parameter> </property>
-
Then open the UnigineEditor, select the desired node, click Add new property and drag the property file to the new property field, then drag all necessary assets and nodes to the corresponding fields of the property (see the video below).Затем откройте UnigineEditor, выберите нужную ноду, нажмите Add new property и перетащите .prop файл в новое поле свойств, затем перетащите все необходимые ассеты и ноды в соответствующие поля свойства (см. видео ниже).
Linking nodes and assets to the propertyПривязка нод и ассетов к свойству -
As we don't use components, we'll have to be bound to names of nodes to which the properties with links to assets are assigned. So, in the init() method of the WorldLogic class we get a node by its name:Поскольку мы не используем компоненты, нам придется привязываться к имени ноды, которой назначено свойство со ссылками на ассеты. Итак, в методе init() класса WorldLogic мы получаем ноду по ее имени:
int AppWorldLogic::init() { /* ... */ NodePtr node = World::getNodeByName("node_name"); /* ... */ return 1; }
-
Then we get a property assigned to it:Затем мы получаем свойство, присвоенное ему:
PropertyPtr property = node->getProperty();
-
Now we can use the property to get access to nodes and files:Теперь мы можем использовать это свойство для получения доступа к нодам и файлам:
-
to get a material we can simply use the corresponding node parameter:чтобы получить материал, мы можем просто использовать соответствующий параметр ноды:
property->getParameterPtr("node_param_name")->getValueMaterial();
-
to get a path to file, we can simply use:чтобы получить путь к файлу, мы можем просто использовать:
As we have a path to our file, we can use it, for example:const char *path = property->getParameterPtr("file_param_name")->getValueFile();
// to create a node reference NodeReferencePtr node_ref = NodeReference::create(path_to_node_file); // to load a sound source SoundSourcePtr sound = SoundSource::create(path_to_sound_file);
-
Let us use an example to illustrate this workflow.Давайте воспользуемся примером, чтобы проиллюстрировать этот подход.
Usage ExampleПример использования#
In this example we are going to manipulate nodes and assets linked to certain node using a property via C++ and C#.В этом примере мы будем работать с нодами и ассетами, связанными с определенной нодой, используя свойство с помощью C++ и C#.
Let us create a simple MeshStatic object named my_object, inherit a material from the mesh_base to assign to the surfaces of our object, and add some audio file (*.mp3 or *.oga) to our project.Давайте создадим простой объект MeshStatic с именем my_object, унаследуем материал от mesh_base для назначения поверхностям нашего объекта и добавим какой-нибудь аудиофайл (*.mp3 или *.oga) в наш проект.
So, we link a *.mesh file, a material, the material_ball node from the default world and an audio file using the property file described above.Итак, мы связываем файл *.mesh, материал, ноду material_ball из мира по умолчанию и аудиофайл, используя .prop файл описанный выше.
In our code we will:В нашем коде мы будем:
- Rotate the linked node.Вращать привязанную ноду.
- Modify linked material and save changes.Изменять привязанную материал и сохранять изменения.
- Generate a new object using a linked mesh.Создавать новый объект, используя привязанный меш.
- Play a linked audio file.Проигрывать привязанный аудиофайл.
C++ ImplementationРеализация на C++#
Below you'll find the C++ implementation of the example described above. You can copy and paste it to the AppWorldLogic.cpp file of your project.Ниже вы найдете реализацию описанного выше примера на C++. Вы можете скопировать и вставить код в файл AppWorldLogic.cpp вашего проекта.
AppWorldLogic.cpp AppWorldLogic.cpp
#include "AppWorldLogic.h"
#include <UnigineMaterials.h>
#include <UnigineSounds.h>
#include <UnigineGame.h>
#include <UnigineWorld.h>
#include <UnigineFileSystem.h>
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
using namespace Unigine;
using namespace Math;
NodePtr my_node; // node to which a property with links is assigned
PropertyPtr property; // property with all necessary links
MaterialPtr material; // linked material
NodePtr param_node; // linked node
SoundSourcePtr sound; // sound source to be played
ObjectMeshStaticPtr generated_obj; // object to be generated using the mesh
AppWorldLogic::AppWorldLogic() {
}
AppWorldLogic::~AppWorldLogic() {
}
int AppWorldLogic::init() {
// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
// getting the node to which a property with links to assets is assigned
my_node = World::getNodeByName("my_object");
// getting the property, that will be used to access all necessary files
property = my_node->getProperty();
// getting a material from the corresponding property parameter
material = property->getParameterPtr("some_material")->getValueMaterial();
// getting the path to the mesh file from the corresponding property parameter
const char *mesh_file_name = property->getParameterPtr("some_mesh")->getValueFile();
// creating the object by using the mesh
generated_obj = ObjectMeshStatic::create(mesh_file_name);
// setting the object position relative to another node position
generated_obj->setWorldPosition(my_node->getWorldPosition());
generated_obj->translate(vec3(-1.0f, 0.0f, 0.0f));
// getting the path to the sound file from the corresponding property parameter
const char *sound_file_name = property->getParameterPtr("some_file")->getValueFile();
// getting a node from the corresponding property parameter
param_node = property->getParameterPtr("some_node")->getValueNode();
// creating and playing a sound from the file
sound = SoundSource::create(sound_file_name);
sound->setMaxDistance(100.0f);
sound->setLoop(1);
sound->play();
// reporting results to the console
Log::message("Path to mesh file: %s\nPath to sound file: %s\nNode ID: %d\n", mesh_file_name, sound_file_name, param_node->getID());
return 1;
}
// start of the main loop
int AppWorldLogic::update() {
// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
float ifps = Game::getIFps();
// changing the material
material->setParameterFloat4("albedo_color", vec4(Game::getRandomFloat(0.0f, 1.0f), Game::getRandomFloat(0.0f, 1.0f), Game::getRandomFloat(0.0f, 1.0f), 1.0f));
// rotate linked node
param_node->setRotation(param_node->getRotation() * quat(0, 0, 30.0f * ifps));
return 1;
}
int AppWorldLogic::postUpdate() {
// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.
return 1;
}
int AppWorldLogic::updatePhysics() {
// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
// The engine calls updatePhysics() with the fixed rate (60 times per second by default) regardless of the FPS value.
// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.
return 1;
}
// end of the main loop
int AppWorldLogic::shutdown() {
// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
// saving current material color (check it in the UnigineEditor to see that it was modified)
material->save();
return 1;
}
int AppWorldLogic::save(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is saving its state: save custom user data to a file.
UNIGINE_UNUSED(stream);
return 1;
}
int AppWorldLogic::restore(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is restoring its state: restore custom user data to a file here.
UNIGINE_UNUSED(stream);
return 1;
}
C# ImplementationРеализация на C##
Below you'll find the C# implementation of the example described above. You can copy and paste it to the AppWorldLogic.cs file of your project.Ниже вы найдете реализацию описанного выше примера на C#. Вы можете скопировать и вставить код в файл AppWorldLogic.cs вашего проекта.
AppWorldLogic.cs AppWorldLogic.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unigine;
namespace UnigineApp
{
class AppWorldLogic : WorldLogic
{
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
Node my_node; // node to which a property with links is assigned
Property property; // property with all necessary links
Material material; // linked material
Node param_node; // linked node
SoundSource sound; // sound source to be played
ObjectMeshStatic generated_obj; // object to be generated using the mesh
public AppWorldLogic()
{
}
public override bool Init()
{
// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
// getting the node to which a property with links to assets is assigned
my_node = World.GetNodeByName("my_object");
// getting the property, that will be used to access all necessary files
property = my_node.GetProperty();
// getting a material from the corresponding property parameter
material = property.GetParameterPtr("some_material").ValueMaterial;
// getting the path to the mesh file from the corresponding property parameter
String mesh_file_name = property.GetParameterPtr("some_mesh").ValueFile;
// creating the object by using the mesh
generated_obj = new ObjectMeshStatic(mesh_file_name);
// setting the object position relative to another node position
generated_obj.WorldPosition = my_node.WorldPosition;
generated_obj.Translate(-1.0f, 0.0f, 0.0f);
// getting the path to the sound file from the corresponding property parameter
String sound_file_name = property.GetParameterPtr("some_file").ValueFile;
// getting a node from the corresponding property parameter
param_node = property.GetParameterPtr("some_node").ValueNode;
// creating and playing a sound from the file
sound = new SoundSource(sound_file_name);
sound.MaxDistance = 100.0f;
sound.Loop = 1;
sound.Play();
// reporting results to the console
Log.Message("Path to mesh file: {0}\nPath to sound file: {1}\nNode ID: {2}\n", mesh_file_name, sound_file_name, param_node.ID);
return true;
}
// start of the main loop
public override bool Update()
{
// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
float ifps = Game.IFps;
// changing the material
material.SetParameterFloat4("albedo_color", new vec4(Game.GetRandomFloat(0.0f, 1.0f), Game.GetRandomFloat(0.0f, 1.0f), Game.GetRandomFloat(0.0f, 1.0f), 1.0f));
// rotate linked node
param_node.SetRotation(param_node.GetRotation() * new quat(0, 0, 30.0f * ifps));
return true;
}
public override bool PostUpdate()
{
// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.
return true;
}
// end of the main loop
public override bool Shutdown()
{
// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
// saving current material color (check it in the UnigineEditor to see that it was modified)
material.Save();
return true;
}
public override bool Save(Stream stream)
{
// Write here code to be called when the world is saving its state: save custom user data to a file.
return true;
}
public override bool Restore(Stream stream)
{
// Write here code to be called when the world is restoring its state: restore custom user data to a file here.
return true;
}
}
}
C++ Component System WorkflowПодход с использованием системы компонентов C++#
If you use C++ Component System in your project, the following workflow is recommended:Если вы используете Компонентную систему C++ в своем проекте, рекомендуется следующая последовательность действий:
- Create a component by inheriting a class from the ComponentBase. The template of this class is available in the UnigineComponentSystem.h header.Создайте компонент, унаследовав класс от ComponentBase. Шаблон этого класса доступен в заголовке UnigineComponentSystem.h.
- Add fields to store links to all necessary nodes and files, materials, meshes, etc. (by using the PROP_PARAM macros).Добавьте поля для хранения ссылок на все необходимые ноды и файлы, материалы, меши и т.д. (с помощью макросов PROP_PARAM).
- Generate a *.prop file for this class (by compiling and running the application).Создайте файл *.prop для этого класса (путем компиляции и запуска приложения).
- Open your world in the UnigineEditor and assign the generated component's property to the desired nodes.Откройте свой мир в UnigineEditor и назначьте свойство сгенерированного компонента нужным нодам.
-
Specify all links to nodes, materials, textures, meshes, other files to be used, by dragging them from the Asset Browser directly to the corresponding field of the property in the Parameters window.Укажите все ноды, материалы, текстуры, меши, другие файлы, которые будут использоваться, перетащив их из Asset Browser непосредственно в соответствующее поле свойства в окне Parameters.
Linking nodes and assets to the property.Привязка нод и ассетов к свойству. - An instance of the component is created when you launch your application. This instance has variables providing access to all used assets. Экземпляр компонента создается при запуске приложения. Этот экземпляр имеет переменные, обеспечивающие доступ ко всем используемым ассетам.
For more detailed information on using C++ Component System, see the C++ Component System Usage Example.Для получения более подробной информации об использовании компонентной системы C++ см. Пример использования компонентной системы C++.
Global Properties for Multiple WorldsГлобальные свойства для нескольких миров#
Sometimes you may need to have a property with links to assets (like described above), that you want to be used in multiple worlds, a sort of global self-sufficient property, not assigned to any node. Such a property can be used, for example, to store settings for a particular type of weapon (FBX-model, shooting sounds, nodes with particle systems for VFX, etc. ) to be used globally in various levels of the game.Иногда вам может понадобиться иметь свойство со ссылками на ассеты (аналогичное описанному выше), которое вы хотите использовать в нескольких мирах, своего рода глобальное самодостаточное свойство, не назначенное ни одной ноде. Такое свойство может быть использовано, например, для хранения настроек для определенного типа оружия (FBX-модель, звуки стрельбы, ноды с системами частиц для визуальных эффектов и т.д.), которые будут использоваться глобально на различных уровнях игры.
The workflow here is as follows:Процедура здесь выглядит следующим образом:
-
First, we create a property to store links to all nodes and assets that we need and save it to our project's data folder. For example, the property can be like this: Сначала мы создаем свойство для хранения ссылок на все ноды и ассеты, которые нам нужны, и сохраняем его в папке data нашего проекта. Например, свойство может быть таким:
<?xml version="1.0" encoding="utf-8"?> <property version="2.16.0.2" name="my_property" parent_name="node_base" manual="1"> <parameter name="some_float" type="float">30.5</parameter> <parameter name="some_string" type="string">Hello from my_property!</parameter> <parameter name="some_node" type="node">0</parameter> <parameter name="some_material" type="material"></parameter> <parameter name="some_mesh" type="file"></parameter> <parameter name="some_file" type="file"></parameter> </property>
-
Then open the UnigineEditor, find the created property in the Properties window, right-click on it and select Create Child. The property named my_property_0 shall be created (you can rename it if you want).Затем откройте UnigineEditor, найдите созданное свойство в окне Properties, щелкните по нему правой кнопкой мыши и выберите Create Child. Должно быть создано свойство с именем my_property_0 (вы можете переименовать его, если хотите).
Create a child propertyСоздайте дочернее свойство -
Level designers make adjustments by dragging all necessary assets and nodes to the corresponding fields of the child property my_property_0, as well as by setting other parameters (if any).Дизайнеры уровней подготавливают нужные настройки, перетаскивая необходимые ассеты и ноды в соответствующие поля дочернего свойства my_property_0, а также устанавливают другие параметры (если таковые имеются).
Linking nodes and assets to the propertyПривязка нод и ассетов к свойству -
Programmers can access any of these assets via this global property from any world. As we don't use components, we'll have to find the property with links to assets by its name (my_property_0). So, in the init() method of the WorldLogic class we do the following:Программисты могут получить доступ к любому из этих ассетов через это глобальное свойство из любого мира. Поскольку мы не используем компоненты, нам нужно будет найти свойство со ссылками на ассеты по его имени (my_property_0). Итак, в методе init() класса WorldLogic мы делаем следующее:
int AppWorldLogic::init() { /* ... */ PropertyPtr property = Properties::findManualProperty("my_property_0"); /* ... */ return 1; }
-
Now we can use the property to get access to nodes and files:Теперь мы можем использовать это свойство для получения доступа к нодам и файлам:
-
to get a material we can simply use the corresponding node parameter: чтобы получить материал, мы можем просто использовать соответствующий параметр ноды:
property->getParameterPtr("node_param_name")->getValueMaterial();
-
to get a path to file, we can simply use: чтобы получить путь к файлу, мы можем просто использовать:
const char *path = property->getParameterPtr("file_param_name")->getValueFile();
As we have a path to our file, we can use it, for example:Поскольку у нас есть путь до нашего файла мы можем, например, использовать его чтобы:
// to create a node reference NodeReferencePtr node_ref = NodeReference::create(path_to_node_file); // to load a sound source SoundSourcePtr sound = SoundSource::create(path_to_sound_file);
-
C++ ImplementationРеализация на C++#
So, C++ implementation of the example (described above) for a global property will be rewritten as shown below. You can copy and paste the code to the AppWorldLogic.cpp file of your project.Итак, реализация примера на C++ (описанная выше) для глобального свойства будет переписана, как показано ниже. Вы можете скопировать и вставить код в файл AppWorldLogic.cpp вашего проекта.
AppWorldLogic.cpp AppWorldLogic.cpp
#include "AppWorldLogic.h"
#include <UnigineMaterials.h>
#include <UnigineSounds.h>
#include <UnigineGame.h>
#include <UnigineWorld.h>
#include <UnigineFileSystem.h>
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
using namespace Unigine;
using namespace Math;
PropertyPtr property; // global property with all necessary links
MaterialPtr material; // linked material
NodePtr param_node; // linked node
SoundSourcePtr sound; // sound source to be played
ObjectMeshStaticPtr generated_obj; // object to be generated using the mesh
AppWorldLogic::AppWorldLogic() {
}
AppWorldLogic::~AppWorldLogic() {
}
int AppWorldLogic::init() {
// getting the property that will be used to access all necessary files using its name
PropertyPtr property = Properties::findManualProperty("my_property_0");
// using access to property parameters to perform desired actions
if(property){
// getting a material from the corresponding property parameter
material = property->getParameterPtr("some_material")->getValueMaterial();
// getting the path to the mesh file from the corresponding property parameter
const char *mesh_file_name = property->getParameterPtr("some_mesh")->getValueFile();
// creating the object by using the mesh
generated_obj = ObjectMeshStatic::create(mesh_file_name);
// setting the object position
generated_obj->setWorldPosition(vec3(-1.0f, 0.0f, 0.0f));
// getting the path to the sound file from the corresponding property parameter
const char *sound_file_name = property->getParameterPtr("some_file")->getValueFile();
// getting a node from the corresponding property parameter
param_node = property->getParameterPtr("some_node")->getValueNode();
// creating and playing a sound from the file
sound = SoundSource::create(sound_file_name);
sound->setMaxDistance(100.0f);
sound->setLoop(1);
sound->play();
// reporting results to the console
Log::message("Path to mesh file: %s\nPath to sound file: %s\nNode ID: %d\n", mesh_file_name, sound_file_name, param_node->getID());
}
return 1;
}
// start of the main loop
int AppWorldLogic::update() {
// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
float ifps = Game::getIFps();
// changing the material
material->setParameterFloat4("albedo_color", vec4(Game::getRandomFloat(0.0f, 1.0f), Game::getRandomFloat(0.0f, 1.0f), Game::getRandomFloat(0.0f, 1.0f), 1.0f));
// rotate linked node
param_node->setRotation(param_node->getRotation() * quat(0, 0, 30.0f * ifps));
return 1;
}
int AppWorldLogic::postUpdate() {
// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.
return 1;
}
int AppWorldLogic::updatePhysics() {
// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
// The engine calls updatePhysics() with the fixed rate (60 times per second by default) regardless of the FPS value.
// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.
return 1;
}
// end of the main loop
int AppWorldLogic::shutdown() {
// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
// saving current material color (check it in the UnigineEditor to see that it was modified)
material->save();
return 1;
}
int AppWorldLogic::save(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is saving its state: save custom user data to a file.
UNIGINE_UNUSED(stream);
return 1;
}
int AppWorldLogic::restore(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is restoring its state: restore custom user data to a file here.
UNIGINE_UNUSED(stream);
return 1;
}
C# ImplementationРеализация на C##
The C# implementation of the example (described above) for a global property will be rewritten as shown below. You can copy and paste the code to the AppWorldLogic.cs file of your project.Реализация примера на C# (описанная выше) для глобального свойства будет переписана, как показано ниже. Вы можете скопировать и вставить код в файл AppWorldLogic.cs вашего проекта.
AppWorldLogic.cs AppWorldLogic.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unigine;
namespace UnigineApp
{
class AppWorldLogic : WorldLogic
{
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
Property property; // global property with all necessary links
Material material; // linked material
Node param_node; // linked node
SoundSource sound; // sound source to be played
ObjectMeshStatic generated_obj; // object to be generated using the mesh
public AppWorldLogic()
{
}
public override bool Init()
{
// getting the property that will be used to access all necessary files using its name
property = Properties.FindManualProperty("my_property_0");
// getting a material from the corresponding property parameter
material = property.GetParameterPtr("some_material").ValueMaterial;
// getting the path to the mesh file from the corresponding property parameter
String mesh_file_name = property.GetParameterPtr("some_mesh").ValueFile;
// creating the object by using the mesh
generated_obj = new ObjectMeshStatic(mesh_file_name);
// setting the object position
generated_obj.WorldPosition = new vec3(-1.0f, 0.0f, 0.0f);
// getting the path to the sound file from the corresponding property parameter
String sound_file_name = property.GetParameterPtr("some_file").ValueFile;
// getting a node from the corresponding property parameter
param_node = property.GetParameterPtr("some_node").ValueNode;
// creating and playing a sound from the file
sound = new SoundSource(sound_file_name);
sound.MaxDistance = 100.0f;
sound.Loop = 1;
sound.Play();
// reporting results to the console
Log.Message("Path to mesh file: {0}\nPath to sound file: {1}\nNode ID: {2}\n", mesh_file_name, sound_file_name, param_node.ID);
return true;
}
// start of the main loop
public override bool Update()
{
// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
float ifps = Game.IFps;
// changing the material
material.SetParameterFloat4("albedo_color", new vec4(Game.GetRandomFloat(0.0f, 1.0f), Game.GetRandomFloat(0.0f, 1.0f), Game.GetRandomFloat(0.0f, 1.0f), 1.0f));
// rotate linked node
param_node.SetRotation(param_node.GetRotation() * new quat(0, 0, 30.0f * ifps));
return true;
}
public override bool PostUpdate()
{
// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.
return true;
}
// end of the main loop
public override bool Shutdown()
{
// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
// saving current material color (check it in the UnigineEditor to see that it was modified)
material.Save();
return true;
}
public override bool Save(Stream stream)
{
// Write here code to be called when the world is saving its state: save custom user data to a file.
return true;
}
public override bool Restore(Stream stream)
{
// Write here code to be called when the world is restoring its state: restore custom user data to a file here.
return true;
}
}
}