This page has been translated automatically.
Видеоуроки
Интерфейс
Основы
Продвинутый уровень
Подсказки и советы
Основы
Программирование на C#
Рендеринг
Профессиональный уровень (SIM)
Принципы работы
Свойства (properties)
Компонентная Система
Рендер
Режимы вывода изображения
Физика
Браузер SDK 2
Лицензирование и типы лицензий
Дополнения (Add-Ons)
Демонстрационные проекты
API Samples
Редактор UnigineEditor
Обзор интерфейса
Работа с ассетами
Контроль версий
Настройки и предпочтения
Работа с проектами
Настройка параметров ноды
Setting Up Materials
Настройка свойств
Освещение
Sandworm
Использование инструментов редактора для конкретных задач
Расширение функционала редактора
Встроенные объекты
Ноды (Nodes)
Объекты (Objects)
Эффекты
Декали
Источники света
Geodetics
World-ноды
Звуковые объекты
Объекты поиска пути
Player-ноды
Программирование
Настройка среды разработки
Примеры использования
C++
C#
UnigineScript
Унифицированный язык шейдеров UUSL (Unified UNIGINE Shader Language)
Плагины
Форматы файлов
Материалы и шейдеры
Rebuilding the Engine Tools
Интерфейс пользователя (GUI)
Двойная точность координат
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
Работа с контентом
Оптимизация контента
Материалы
Визуальный редактор материалов
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Учебные материалы

Обработка событий

When writing your application logic, one of the biggest challenges you're likely to face is connecting the various changing elements in a way that works. For example, making a character move, jump, or adding up the score can be relatively easy to do on its own. But connecting all things that happen in your game or application without making it confusing to work with can be very challenging.При написании логики приложения одна из самых больших проблем, с которой вы, вероятно, столкнетесь, — это взаимосвязь различных изменяющихся элементов таким образом, чтобы это работало. Например, заставить персонажа двигаться, прыгать или получать очки может быть относительно легко само по себе. Но связать все, что происходит в вашей игре или приложении, не создавая путаницы в работе, может быть очень сложно.

The Event System enables you to create application logic that is executed when an event is triggered during the application execution. It allows objects to subscribe one or more of their own functions to a subject's event. Then, when the subject triggers the event, the objects' functions are called in response. Such functions are also known as event handlers. Система событий позволяет создавать логику приложения, которая выполняется при запуске события во время выполнения приложения. Она позволяет объектам подписывать одну или несколько своих собственных функций на событие субъекта. Затем, когда субъект запускает событие, в ответ вызываются функции объектов. Такие функции также известны как обработчики событий.

The Event System features the following:Система событий включает в себя следующее:

  • Strict type checking for signatures: you can see how many and which exactly arguments an event handler function requires. Строгая проверка типов для подписей: вы можете увидеть, сколько и какие именно аргументы требуются функции-обработчику событий.
  • Compile-time checking: it ensures that argument types match event types, preventing runtime errors. Проверка во время компиляции: она гарантирует, что типы аргументов соответствуют типам событий, предотвращая ошибки во время выполнения.
  • Simple subscription/unsubscription to events with lambda functions with no need to perform internal type conversions. Простая подписка/отмена подписки на события с помощью лямбда-функций без необходимости выполнять внутренние преобразования типов.
  • Automatic event unsubscription. Автоматическая отмена подписки на событие.
  • Temporary event deactivation: particular events can be temporarily disabled to perform specific actions without triggering them. Временная деактивация событий: определенные события можно временно отключить для выполнения определенных действий без их запуска.
  • Batch management: you can unsubscribe from several subscriptions in a single function call. Пакетное управление: вы можете отказаться от нескольких подписок одним вызовом функции.

Events
События#

An event is represented by the abstract Event class. It serves as an interface for interaction with the event. Typically, you get this interface via a reference as Event<args...>, where args represents a list of arguments the event will pass to a handler function.Событие представлено абстрактным классом Event. Он служит интерфейсом для взаимодействия с событием. Как правило, вы получаете этот интерфейс через ссылку в виде Event<args...>, где args представляет список аргументов, которые событие передаст функции-обработчику.

For example, Body.EventPosition returns the event with the following signature:Например, Body.EventPosition возвращает событие со следующей сигнатурой:

Исходный код (C#)
Event<Body>

It means the handler function must receive an argument of the same type when connected with the event.Это означает, что функция-обработчик должна получать аргумент того же типа при подключении к событию.

Emulating Events
Имитация событий#

Sometimes, it is necessary to emulate events. For custom events, you can use the EventInvoker.Run() function that receives the same arguments as the event and invokes its handler functions.Иногда необходимо имитировать события. Для пользовательских событий вы можете использовать функцию EventInvoker.Run(), которая получает те же аргументы, что и событие, и вызывает его функции-обработчики.

The following example shows how to create your event and then run it when necessary:В следующем примере показано, как создать собственное событие, а затем запустить его при необходимости:

Исходный код (C#)
class MyEventClass
{
	public Event<int> MyEvent { get { return my_event; } }

	public void RunEvent()
	{
		num_runs++;
		my_event.Run(num_runs);
	}

	private int num_runs = 0;
	private EventInvoker<int> my_event = new EventInvoker<int>();
};

static void Main(string[] args)
{
	MyEventClass my_class = new MyEventClass();

	my_class.MyEvent.Connect(
		(int n) =>
		{
			System.Console.WriteLine("n = {0}", n);
		}
	);

	my_class.RunEvent();
	my_class.RunEvent();
}

The existing events that are implemented for built-in objects and available through API can be emulated using the corresponding RunEvent*() methods (without having to use EventInvoker.Run()). For example, to emulate the Show event for a widget, call Widget.RunEventShow().Существующие события, которые реализованы для встроенных объектов и доступны через API, могут быть имитированы с использованием соответствующих методов RunEvent*() (без необходимости использовать EventInvoker.Run()). Например, чтобы имитировать событие Show для виджета, вызовите Widget.RunEventShow().

Исходный код (C#)
widget.RunEventShow();

Event Handlers
Обработчики событий#

The event handler functions can receive no more than 5 arguments.Функции-обработчики событий могут принимать не более 5 аргументов.

In addition, the Event System performs strict type checking for handler function signatures: you can subscribe to the event only if the types of the function arguments match the event types. For example, in the case of the event with a single int argument, you are only able to link it with a handler that also accepts a single integer argument. Even if the types can be implicitly converted (as in the example), subscribing is not permitted.Кроме того, система событий выполняет строгую проверку типов сигнатур функций-обработчиков: вы можете подписаться на событие только в том случае, если типы аргументов функции соответствуют типам событий. Например, в случае события с одним аргументом int вы можете связать его только с обработчиком, который также принимает один целочисленный аргумент. Даже если типы могут быть преобразованы неявно (как в примере), подписка не допускается.

Исходный код (C#)
Event<int> event; // event signature
void on_event(int a); 	// types match, subscription is allowed
void on_event(long a); 	// type mismatch, no subscription

This restriction also applies to the in, out, and ref modifiers. For instance, when the event type is a user class with no modifiers:Это ограничение также применяется к модификаторам in, out и ref. Например, когда типом события является пользовательский класс без модификаторов:

Исходный код (C#)
Event<MyClass> event;
void on_event(MyClass a);		// types match, subscription is allowed
void on_event(out MyClass a);	// type mismatch
void on_event(in MyClass a);	// type mismatch

Discarding Arguments
Отбрасывание аргументов#

In most cases, not all arguments passed to the handler function by the event are necessary. So, events allow for discarding unnecessary arguments when functions subscribe to them. You can only discard one argument at a time, starting with the last one. For example, the following handler functions can subscribe to the event:В большинстве случаев не все аргументы, передаваемые функции-обработчику событием, необходимы. Таким образом, события позволяют отбрасывать ненужные аргументы, когда функции подписываются на них. Вы можете отбрасывать только один аргумент за раз, начиная с последнего. Например, следующие функции-обработчики могут подписаться на событие:

Исходный код (C#)
// the event
Event<int, float, string, vec3, MyClass> event;

// the event handlers with discarded arguments
on_event(int a, float b, string s, vec3 v, MyClass c);
on_event(int a, float b, string s, vec3 v);
on_event(int a, float b, string s);
on_event(int a, float b);
on_event(int a);
on_event();

Receiving Additional Arguments
Получение дополнительных аргументов#

To receive an additional user argument in the handler function, you need to add the required argument to the end of the handler arguments list and pass its value to the Connect() function.Чтобы получить дополнительный пользовательский аргумент в функции-обработчике, вам нужно добавить требуемый аргумент в конец списка аргументов обработчика и передать его значение функции Connect().

Исходный код (C#)
class UserClass
{
	{ /* ... */ }
};

static EventInvoker<int, float> my_event = new EventInvoker<int, float>();

void on_event_0(int a, float b, int my_var) { /* ... */ }

void on_event_1(int a, float b, UserClass c) { /* ... */ }

void on_event(float f, string str) { /* ... */ }

static MyClass my_class = new MyClass();

static void Main(string[] args)
{
	// pass the value of the additional "my_var" argument to the handler function
	my_event.Connect(on_event_0, 33);
	// pass the value of the additional "c" argument to the handler function
	my_event.Connect(on_event_1, my_class);
	// discard the int and float handler arguments, add the custom float and const char* and pass them to connect()
	my_event.Connect(on_event, 33.3f, "test");

	return 0;
}

Subscribing to Events
Подписка на события#

For convenience, the Event System provides the EventConnection and EventConnections classes that allow simple event subscription/unsubscription. Let's go through them in detail.Для удобства система событий предоставляет классы EventConnection и EventConnections, которые позволяют просто подписаться на событие или отписаться от него. Давайте рассмотрим их подробнее.

Single Subscription with EventConnection
Единая подписка с EventConnection#

The EventConnection class keeps a connection between an event and its handler. You can subscribe to events via the Event.Connect() function and unsubscribe via Event.Disconnect():Класс EventConnection поддерживает связь между событием и его обработчиком. Вы можете подписаться на события с помощью функции Event.Connect() и отписаться с помощью Event.Disconnect():

  • The Connect() function receives the handler function as an argument. It returns EventConnection that can be used to unsubscribe from the event. The number of the Connect() function arguments may vary.Функция Connect() принимает функцию-обработчик в качестве аргумента. Она возвращает значение EventConnection, которое можно использовать для отмены подписки на событие. Количество аргументов функции Connect() может варьироваться.
  • The Disconnect() function receives the handler function as an argument.Функция Disconnect() получает функцию-обработчик в качестве аргумента.

For example, to set the connection between the event and the static handler function, you can implement the following:Например, чтобы установить связь между событием и статической функцией-обработчиком, вы можете реализовать следующее:

Исходный код (C#)
static EventInvoker<int, float> my_event = new EventInvoker<int, float>();

// a static handler function
static void on_event(int a, float b) { /*...*/ }

static void Main(string[] args)
{
	// connect the handler function with the event
	EventConnection connection = my_event.Connect(on_event);
}

You can temporarily turn the event off to perform specific actions without triggering it.Вы можете временно отключить событие, чтобы выполнить определенные действия, не запуская его.

Исходный код (C#)
// disable the event
my_event.Enabled = false;

/* perform some actions */

// and enable it again
my_event.Enabled = true;

Moreover, you can toggle individual connections on and off, providing flexibility when working with events.Кроме того, вы можете включать и выключать отдельные подключения, обеспечивая гибкость при работе с событиями.

Исходный код (C#)
EventConnection connection = my_event.Connect(on_event);
/* ... */

// disable the connection
connection.Enabled = false;

/* perform some actions */

// and enable it back when necessary
connection.Enabled = true;

Later, you can unsubscribe from the event in one of the following ways:Позже вы можете отписаться от события одним из следующих способов:

  • By using the handler function:С помощью функции-обработчика:

    Исходный код (C#)
    // break the connection by using the handler function
    my_event.Disconnect(on_event);
  • By using EventConnection:С помощью EventConnection:

    Исходный код (C#)
    // break the connection by using EventConnection
    connection.Disconnect()

If the handler function is a class method, you should create a class instance, subscribe to the event, and unsubscribe later as follows:Если функция-обработчик является методом класса, создавать экземпляр класса, подписываться на событие и отписываться от него позже нужно следующим образом:

Исходный код (C#)
class MyClass
{
	public void on_event(int a, float b) { /*...*/ }
}

static EventInvoker<int, float> my_event = new EventInvoker<int, float>();

static void Main(string[] args)
{
    MyClass obj = new MyClass();

	// connect the handler function with the event
	EventConnection connection = my_event.Connect(obj.on_event);

	/* ... */

	// break the connection by using the handler function later
	my_event.Disconnect(obj.on_event);
}

Multiple Subscriptions with EventConnections
Несколько подписок с подключениями к событиям#

The EventConnections class is a container for the EventConnection instances. Multiple subscriptions to a single event or different events can be linked to a single EventConnections instance. Класс EventConnections является контейнером для экземпляров EventConnection. Несколько подписок на одно событие или разные события могут быть связаны с одним экземпляром EventConnections.

For example, you can create multiple subscriptions to a single event as follows:Например, вы можете создать несколько подписок на одно событие следующим образом:

Исходный код (C#)
EventConnections connections = new EventConnections();

static EventInvoker my_event = new EventInvoker();

// event handlers
void on_some_event_0() { Log.Message("\Handling the 1st event\n"); }
void on_some_event_1() { Log.Message("\Handling the 2nd event\n"); }

void init()
{
	// add two handlers for the event
	// and link it to an EventConnections instance to remove a pack of subscriptions later
	my_event.Connect(connections, on_some_event_0);
	my_event.Connect(connections, on_some_event_1);
}

Also, you can create multiple subscriptions to different events:Кроме того, вы можете создать несколько подписок на разные события:

Исходный код (C#)
EventConnections connections = new EventConnections();

static EventInvoker my_event_0 = new EventInvoker();
static EventInvoker my_event_1 = new EventInvoker();

// event handlers
void on_some_event_0() { Log.Message("\Handling the 1st event\n"); }
void on_some_event_1() { Log.Message("\Handling the 2nd event\n"); }

void init()
{
	// subscribe for events with handlers to be executed when the events are triggered;
	// here multiple subscriptions are linked to a single EventConnections class instance
	my_event_0.Connect(connections, on_some_event_0);
	my_event_1.Connect(connections, on_some_event_1);
}

Later all of these linked subscriptions can be removed with a single line:Позже все эти связанные подписки могут быть удалены одной строкой:

Исходный код (C#)
// break the connection by using EventConnections
// all instances of EventConnection will be removed from the EventConnections container
connections.DisconnectAll();

Using Lambda Functions
Использование лямбда-функций#

You can pass a lambda function as an argument to the Connect() function to handle the event: there is no need to perform internal type conversions. All features available for the handler functions are also applicable to lambda functions, except additional arguments.Вы можете передать лямбда-функцию в качестве аргумента функции Connect() для обработки события: нет необходимости выполнять внутренние преобразования типов. Все функции, доступные для функций-обработчиков, также применимы к лямбда-функциям, за исключением дополнительных аргументов.

Исходный код (C#)
class MyClass
{
};

static EventInvoker<int, float> my_event = new EventInvokerlt;int, float>();

static void Main(string[] args)
{
	EventConnection connection = my_event.Connect(
		(int a, float b) =>
		{
			System.Console.WriteLine("a = {0}, b = {1}", a, b);
		},
	);

	connection = my_event.Connect(
		(int a) =>
		{
			System.Console.WriteLine("a = {0}", a);
		},
	);

	connection = my_event.Connect(
		(int a, string s) =>
		{
			System.Console.WriteLine("a = {0}, s = {1}", a, s);
		},
		"my string"
	);

	connection = my_event.Connect(
		(int a, float b, string s) =>
		{
			System.Console.WriteLine("a = {0}, b = {1}, s = {2}", a, b, s);
		},
		"test"
	);

	my_event.Run(3, 33.0f);
}

See more examples of practical use of lambda functions below.Далее в статье есть дополнительные примеры практического использования лямбда-функций.

Using Predefined Events
Использование предопределенных событий#

Some Unigine API members have several predefined events that can be handled in specific cases. The following chapters showcase the practical use of the concepts described above.Для некоторых членов Unigine API существует ряд предопределенных событий, которые могут обрабатываться в конкретных случаях. В следующих главах демонстрируется практическое использование концепций, описанных выше.

Triggers
Триггеры#

Triggers are used to detect changes in nodes position or state. Unigine offers three types of built-in triggers:Триггеры используются для обнаружения изменений в положении или состоянии нод. Unigine предлагает три типа встроенных триггеров:

Here is a simple NodeTrigger usage example. The event handlers are set via pointers specified when subscribing to the following events: EventEnabled and EventPosition.Вот простой пример использования NodeTrigger. Обработчики событий устанавливаются с помощью указателей, заданных при подписке на следующие события: EventEnabled и EventPosition.

Исходный код (C#)
private NodeTrigger trigger;
private ObjectMeshStatic obj;

// the position event handler
void position_event_handler(NodeTrigger trigger)
{
	Log.Message("Object position has been changed. New position is: {0}\n", trigger.WorldPosition.ToString());
}
// the enabled event handler
void enabled_event_handler(NodeTrigger trigger)
{
	Log.Message("The enabled event handler is {0}\n", trigger.Enabled);
}

private void Init()
{

	// create a mesh
	Mesh mesh = new Mesh();
	mesh.AddBoxSurface("box_0", new vec3(1.0f));
	// create a node (e.g. an instance of the ObjectMeshStatic class)
	obj = new ObjectMeshStatic("core/meshes/box.mesh");
	// change material albedo color
	obj.SetMaterialParameterFloat4("albedo_color", new vec4(1.0f, 0.0f, 0.0f, 1.0f), 0);
	// create a trigger node
	trigger = new NodeTrigger();
	
	// add it as a child to the static mesh
	obj.AddWorldChild(trigger);

	// add the enabled event handler to be executed when the node is enabled/disabled
	trigger.EventEnabled.Connect(enabled_event_handler);
	// add the position event handler to be executed when the node position is changed
	trigger.EventPosition.Connect(position_event_handler);

}

private void Update()
{

	float time = Game.Time;
	Vec3 pos = new Vec3(MathLib.Sin(time) * 2.0f, MathLib.Cos(time) * 2.0f, 0.0f);
	// change the enabled flag of the node
	obj.Enabled = pos.x > 0.0f || pos.y > 0.0f;
	// change the node position
	obj.WorldPosition = pos;

}

And here is an example of WorldTrigger that demonstrates how to subscribe to the Enter event with a corresponding handler and keep this connection to unsubscribe later.А вот пример WorldTrigger, который демонстрирует, как подписаться на событие Enter с помощью соответствующего обработчика и сохранить это подключение, чтобы отписаться позже.

Исходный код (C#)
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif

[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class EventHandlers : Component
{
		// implement the Enter event handler
		void enter_event_handler(Node node)
		{
			Log.Message("\nA node named {0} has entered the trigger\n", node.Name);
		}
		// implement the Leave event handler
		void leave_event_handler(Node node)
		{
			Log.Message("\nA node named {0} has left the trigger\n", node.Name);
		}
		WorldTrigger trigger;
		EventConnection enter_event_connection;
	
	private void Init()
	{
		// create a world trigger
		trigger = new WorldTrigger(new vec3(3.0f));
		// subscribe to the enter event with a handler to be executed when a node enters the world trigger
		// and keep its connection to be used to unsubscribe when necessary
		enter_event_connection = trigger.EventEnter.Connect(enter_event_handler);
		// add the leave event handler to be executed when a node leaves the world trigger
		trigger.EventLeave.Connect(leave_event_handler);
	}

	private void Update()
	{
	}

	private void Shutdown()
	{
		// removing the subscription for the Enter event by using the connection (enter_event_connection)
		enter_event_connection.Disconnect();
	}
}

Widgets
Виджеты#

The widgets base class Widget allows subscribing to events.Базовый класс виджетов Widget позволяет подписываться на события.

The example below demonstrates how to set a lambda function to handle the widget's Clicked event.В приведенном ниже примере показано, как настроить лямбда-функцию для обработки события Clicked виджета.

Исходный код (C#)
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif

[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class EventHandlers : Component
{
	
	private void Init()
	{
		// get the system GUI
		Gui gui = Gui.GetCurrent();

		// create a button widget and set its caption
		WidgetButton widget_button = new WidgetButton(gui, "Press me");

		// rearrange a button size
		widget_button.Arrange();

		// set a button position
		widget_button.SetPosition(10,10);

		// set a lambda function to handle the CLICKED event
		widget_button.EventClicked.Connect(() => Log.Message("Button pressed\n"));

		// add the created button widget to the system GUI
		gui.AddChild(widget_button, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
	}
}

Physics
Физика#

You can track certain events of the physics-related Bodies and Joints:Вы можете отслеживать определенные события, связанные с физическими телами и сочленениями:

  • Body.EventFrozen to track an event when a body freezes. Body.EventFrozen для отслеживания события, когда тело прекращает движение.
  • Body.EventPosition to track an event when a body changes its position.Body.EventPosition для отслеживания события, когда тело меняет свое положение.
  • Body.EventContactEnter to track an event when a contact emerges (body starts touching another body or collidable surface).Body.EventContactEnter для отслеживания события, когда возникает контакт (тело начинает касаться другого тела или коллизионной поверхности).
  • Body.EventContactLeave to track an event when a contact ends (body stops touching another body or collidable surface).Body.EventContactLeave для отслеживания события, когда контакт прекращается (тело перестает касаться другого тела или коллизионной поверхности).
  • Body.EventContacts to get all contacts of the body including new ones (enter) and the ending ones (leave). Leave contacts are removed after the callback execution stage, so this is the only point where you can still get them.Body.EventContacts, чтобы получить все контакты тела, включая возникающие (входящие) и прекращающиеся (выходящие). Прекращающиеся контакты удаляются после этапа выполнения обратного вызова, так что это единственная точка, где вы все еще можете их получить.
  • Joint.EventBroken to track an event when a joint breaks.Joint.EventBroken для отслеживания события при разрыве подключения.

The following example demostrates how to subscribe to the Body events by using lambda functions and then remove all the event subscriptions for the Body.В следующем примере показано, как подписаться на события Body с помощью лямбда-функций, а затем удалить все подписки на события для Body.

Исходный код (C#)
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif

[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class EventHandlers : Component
{
		EventConnections body_event_connections = new EventConnections();
	
	private void Init()
	{
		// create a box
		ObjectMeshStatic meshStatic = new ObjectMeshStatic("core/meshes/box.mesh");
		meshStatic.Position = new Vec3(0, 0, 5.0f);

		// add a rigid body to the box
		BodyRigid body = new BodyRigid(meshStatic);

		// subscribe for body events by using lambda functions and storing connections to remove them later
		body.EventFrozen.Connect(body_event_connections, b => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(1.0f, 0.0f, 0.0f, 1.0f), 0));
		body.EventPosition.Connect(body_event_connections, b => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(0.0f, 0.0f, 1.0f, 1.0f), 0));
		body.EventContactEnter.Connect(body_event_connections, (b, num) => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(1.0f, 1.0f, 0.0f, 1.0f), 0));

		// add a shape to the body
		ShapeBox shape = new ShapeBox(body, new vec3(1.0f));
	}
	private void Shutdown()
	{
		// removing all previously stored event subscriptions for the body
		body_event_connections.DisconnectAll();
	}
}
Примечание
Physics-based events are executed in the main thread, as they are mainly used for creation, destruction or modification of other objects.События, связанные с физикой, выполняются в основном потоке, поскольку они в основном используются для создания, уничтожения или модификации других объектов.

Properties
Свойства#

Events can be used to determine actions to be performed when adding or removing node and surface properties as well as when swapping node properties. Here is an example demonstrating how to track adding a node property via events.События могут использоваться для определения действий, которые необходимо выполнить при добавлении или удалении свойств ноды и поверхности, а также при переключении свойств ноды. Вот пример, демонстрирующий, как отслеживать добавление свойства ноды с помощью событий.

Исходный код (C#)
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif

[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class EventHandlers : Component
{
		void node_property_added(Node n, Property property)
		{
			Log.Message("Property \"{0}\" was added to the node named \"{1}\".\n", property.Name, n.Name);
		}
		void parameter_changed(Property property, int num)
		{
			Log.Message("Parameter \"{0}\" of the property \"{1}\" has changed its value.\n", property.GetParameterPtr(num).Name, property.Name);
		}
		public void property_removed(Property property)
		{
			Log.Message("Property \"{0}\" was removed.\n", property.Name);
		}
	
	private void Init()
	{
		NodeDummy node = new NodeDummy();

		// search for a property named "new_property_0"
		Property property = Properties.FindProperty("new_property_0");
		
		// subscribing for the PropertyNodeAdd event to handle adding a property to a node
		Node.EventPropertyNodeAdd.Connect(node_property_added);

		// add the property named "new_property_0" to the node
		node.AddProperty("new_property_0");
		// subscribing for the ParameterChange event to handle changing property parameter
		property.EventParameterChanged.Connect(parameter_changed);

		// change the value of the "my_int_param" parameter
		property.GetParameterPtr("my_int_param").SetValue(3);
		// inherit a new property named "new_property_1" from the base property "surface_base"
		Properties.FindManualProperty("surface_base").Inherit("new_property_1");

		// subscribing for property removal event
		Properties.EventRemoved.Connect(property_removed);

		// remove the property named "new_property_1"
		Properties.RemoveProperty(Properties.FindProperty("new_property_1").GUID);
	}
}
Последнее обновление: 13.12.2024
Build: ()