Документация/Статьи по программированию/Система сущностей

From NeoAxis Engine Wiki

Jump to: navigation, search
Перейти на уровень выше

Contents

Описание

Здесь рассмотрена система сущностей на уровне программиста. Описана структура системы и основные классы API системы сущностей.

Перед изучением данного описания, рекомендуем познакомиться с введением в систему игровых объектов.

Урок по созданию нового игрового класса также будет полезен.

Основные классы системы игровых объектов:

  • Entity - Класс экземпляра игрового объекта в мире или класс игрового объекта. Свойства данного класса доступны в редакторе карт для редактирования.
  • EntityType - Класс типа игрового объекта. Свойства данного класса доступны в редакторе игровых объектов.
  • Entities - Класс менеджера игровых объектов. Создание новых объектов, функции для работы с коллекцией объектов и другие.
  • EntitySystemWorld - Класс для общего управления системой сущностей.

Код системы объектов находится в сборке EntitySystem.dll.

Структура игровых объектов

Все игровые объекты образуют структуру в виде дерева, в корне которого находится объект класса World. Каждый объект (за исключением корневого) имеет родителя и может иметь детей.

Мир игровых объектов представляет собой иерархическую структуру, в корне которой лежит объект класса World. У каждого объекта, кроме корневого World, есть свой родитель.

В определенный момент времени иерархия может быть такой:

WorldHierarchy.jpg

Создание/удаление объектов

Создание объектов

Порядок создания объекта следующий:

  • Создание объекта по средствам вызова метода Entities.Create().
  • Далее настраиваются дополнительно начальные параметры (например положение объекта).
  • Наконец, вызывается метод PostCreate(), который добавляет объект в игровой мир. Теперь объект является проинициализированным.

Пример создания ящика на карте:

MapObject obj = (MapObject)Entities.Instance.Create( "Box", Map.Instance );
obj.Position = new Vec3( 0, 0, 10 );
obj.PostCreate();

Порядок вывозов виртуальных методов и событий при создании объекта

В течении создания объекта вызываются различные виртуальные методы класса и события. Эти методы можно переопределять и добавлять свой функционал.

Порядок вызова методов и событий вызываемых для создания игрового объекта:

Порядок вызова методов и событий при загрузке игрового объекта:

Предупреждение: Метод OnCreate() и событие Create вызываются только при создании объекта. Во время загрузки они не будут вызываться.

Удаление объектов

Стандартное удаление объекта осуществляется с помощью метода SetShouldDelete().

пример:

MapObject obj = ...;
obj.SetShouldDelete();

Чтобы удалить игровой объект можно использовать методы SetShouldDelete() или SetDeleted().

Разница между этими двумя методами в том, что метод SetShouldDelete() позволяет отложить удаление объекта на определенное время. Это бывает полезно при проектировании игровой логики. Задержка удаления объекта осуществляется с помощью переопределения виртуального метода OnShouldDelete(). Метод SetDeleted() удаляет игровой объект сразу же. Предпочтительнее использовать метод SetShouldDelete(), т.к. как удаляемый игровой объект имеет возможность совершить необходимые действия перед удалением.

Специфика демо: В демо для Dynamic-классов нужно использовать метод Die().

Порядок вывозов виртуальных методов и событий при удалении объекта

Обратите внимание на то, что в процессе вызова метода OnShouldDelete() удаление объекта может быть отложено на определенное время.

API

Класс Entities

Имя Описание
PublicMethod.gif Entity Create( EntityType type, Entity parent ) Создание игрового объекта указанного типа.
PublicMethod.gif Entity Create( String typeName, Entity parent ) Создание игрового объекта с типом, соответствующим указанному имени типа.
Event.gif CreateEntity Событие, вызываемое при создании игрового объекта.
Event.gif DeleteEntity Событие, вызываемое при удалении игрового объекта.

Класс Entity

Имя Описание
PublicMethod.gif void PostCreate() Метод, добавляющий игровой объект в игровой мир. Вызывается после того как заданы параметры игрового объекта.
ProtectedMethod.gif VirtualMember.gif void OnPreCreate() Метод, вызываемый сразу после создания объекта.
ProtectedMethod.gif VirtualMember.gif void OnCreate() Метод, вызываемый после того как игровой объект создан в игровом мире. Этот метод не вызывается, если объект загружен.
Event.gif Create Событие, вызываемое после того как игровой объект создан в игровом мире. Это событие не срабатывает, если объект загружен.
Event.gif PostCreated Событие, вызываемое после того как игровой объект добавлен в игровой мир.
ProtectedMethod.gif VirtualMember.gif void OnPostCreate( Boolean loaded ) Метод, вызываемый после того как игровой объект добавлен в игровой мир.
ProtectedMethod.gif VirtualMember.gif void OnPostCreate2( Boolean loaded ) Метод, вызываемый после того как игровой объект добавлен в игровой мир. Вызывается после метода OnPostCreate.
PublicProperty.gif bool IsPostCreated Свойство принимает значение True, если объект уже создан и добавлен в игровой мир. В противном случае свойство принимает значение False.
PublicMethod.gif void SetShouldDelete() Метод, информирующий о том, что игровой объект должен быть удален.
ProtectedMethod.gif VirtualMember.gif bool OnShouldDelete() Метод, вызываемый после в течении вызова SetShouldDelete.
PublicMethod.gif void SetDeleted() Удаляет игровой объект из игрового мира.
ProtectedMethod.gif VirtualMember.gif void OnDestroy() Метод, вызываемый после удаления объекта из игрового мира.
Event.gif Destroying Событие, вызываемое при перед тем как объект будет удален из игрового мира.

Именование объектов

Описание

Каждый игровой объект имеет имя, доступ к которому осуществляется с помощью свойства Name.

Имя каждого игрового объекта уникально. При создании нового объекта, ему дается уникальное имя в виде {имя игрового типа}_{уникальный номер}.

Также, имя может быть пустым, если свойство EntityType.AllowEmptyName типа игрового объекта установлено в значение True. Вы можете настроить данное свойство во время редактирования типа в редакторе игровых объектов.

API

Класс EntityType

Имя Описание
PublicProperty.gif Boolean AllowEmptyName Задает и возвращает значение, разрешающее или запрещающее игровому объекту иметь пустое имя.

Класс Entity

Имя Описание
ProtectedMethod.gif VirtualMember.gif void OnNameChange() Метод, вызываемый при изменении имени объекта.
PublicProperty.gif string Name Имя объекта.
Event.gif NameChanged Событие, вызываемое после изменения имени игрового объекта.

Класс Entities

Имя Описание
PublicMethod.gif Entity GetByName( String name ) Метод, возвращающий игровой объект по его имени.
PublicMethod.gif string GetUniqueName( String prefix ) Метод, возвращающий сгенерированное уникальное имя с префиксом.

Тики и таймеры

Описание

Симуляция игрового мира происходит через постоянные интервалы времени. По умолчанию, происходит 30 тиков в секунду. Когда идет симуляция, игровые объекты получают уведомления о тиках.

Либой игровой объект может принимать уведомления о тиках игрового мира. Чтобы принимать уведомления, игровой объект должен подписаться на них. Необходимость в подписывании на уведомления связано с проблемами производительности. Нет необходимости подписывать все игровые объекты на уведомления о тиках.

Счетчики таймеров не сериализуются, поэтому их необходимо восстанавливать после загрузки.

Вы можете изменить количество тиков в секунду в файле "Definitions/EntitySystem.config", но делать это не рекомендуется.

Пример

Пример подписки на события таймера и получения уведомлений о тиках:

class MyEntity : Entity
{
    protected override void OnPostCreate( bool loaded )
    {
        base.OnPostCreate( loaded );
        AddTimer();
    }
 
    protected override void OnTick()
    {
        base.OnTick();
 
        float delta = TickDelta;
        ...
    }
}

API

Класс Entity

Имя Описание
PublicMethod.gif void AddTimer() Увеличение числа подписок на события таймера.
PublicMethod.gif void RemoveTimer() Уменьшение числа подписок на события таймера.
ProtectedMethod.gif VirtualMember.gif void Client_OnTick() Метод, вызываемый каждый игровый тик в приложении. Работает только в сетевом режиме на стороне клиента.
Event.gif Tick Событие, вызываемое при каждом игровом тике.
PublicProperty.gif StaticMember.gif float TickDelta Константа равная времени между тиками в секундах. По умолчанию равна 1/30 секунды.

Класс EntitySystemWorld

Имя Описание
PublicProperty.gif Boolean Simulation Остановить или продолжить симуляцию.
PublicProperty.gif Single GameFPS Возвращает постоянную, равную количеству тиков в секунду. По умолчанию равно 30 кадрам в секунду.

Связи (уведомления об удалении объектов)

Описание

Система связей позволяет получать уведомления об удалении определенного игрового объекта. Бывает возникает задача, когда необходимо оповестить один игровой объект об удалении другого. Данная система решает эту задачу.

Два игровых объекта могут установить связь и каждый из объектов получит уведомление об удалении другого объекта. Связи устанавливаются между двумя игровыми объектами и, когда один из связанных объектов удаляется, другой получает сообщение (вызов виртуального метода). Связи симметричны и не существует главных и зависимых объектов.

Связи сериализуются, поэтому нет необходимости восстанавливать их при загрузке.

Пример

Ниже приведен пример создания связи и обработки оповещения об удалении связанного игрового объекта:

class MyEntity : Entity
{
	Entity someEntity;
 
	void SomeMethod( Entity entity )
	{
		someEntity = entity;
		AddRelationship( someEntity );
	}
 
	protected override void OnRelatedEntityDelete( Entity entity )
	{
		base.OnRelatedEntityDelete( entity );
 
		if( someEntity == entity )
			someEntity = null;
	}
}

API

Класс Entity

Имя Описание
PublicMethod.gif void AddRelationship( Entity entity ) Создание связи. При удалении связанного объекта, игровой объект получит уведомление (вызов виртуального метода OnRelatedEntityDelete).
PublicMethod.gif void RemoveRelationship( Entity entity ) Удаление связи.
ProtectedMethod.gif VirtualMember.gif void OnRelationshipAdd( Entity entity ) Метод, вызываемый при добавлении связи к объекту.
ProtectedMethod.gif VirtualMember.gif void OnRelationshipRemove( Entity entity ) Метод, вызываемый при удалении связи с объектом.
ProtectedMethod.gif VirtualMember.gif void OnRelatedEntityDelete( Entity entity ) Метод, вызываемый при удалении связанного объекта.
Event.gif RelatedEntityDelete Событие, вызываемое при удалении связанного объекта.

Сериализация объектов

Описание

Для сохранения карты или мира существует единая система для сериализации. Сериализация заключается в том, чтобы сохранить значения переменных объекта (или типа объекта), и в будущем их восстановить.

Сериализацию можно разделить на два типа:

  • Сериализация типов игровых объектов (загрузка/сохранения файлов ".type").
  • Сериализация игровых объектов (загрузка/сохранение игрового мира и карты).

Оба типа имеют похожий синтаксис. Далее будет рассматриваться сериализация обоих типов.

Существует два способа сериализации переменных:

Способ с атрибутом

Сериализация при помощи атрибута проста в использовании, но имеет ограничения по функциональности. Данный способ позволяет сохранять практически все типы (базовые типы .NET, игровые объекты, типы игровых объектов, массивы и списки), но при нестандартных данных такой метод сериализации не подходит.

Поддерживаемые типы:

  • Простые типы: bool, sbyte, byte, short, ushort, char, int, uint, long, ulong, float, double.
  • Структуры: Vec2, Vec3, Vec4, Bounds, Range, ColorValue, SphereDir, Rect, Vec2i, Vec3i, Recti, Degree, Radian.
  • Строки.
  • Перечисления.
  • Классы, основанные на EntityType.
  • Классы, основанные на Entity.
  • Произвольные структуры и классы.
  • Массивы( T[] ).
  • Списки ( List<T> ).

Способ с OnLoad/OnSave

Если способа с атрибутом недостаточно, можно использовать методы OnLoad()/OnSave() method. Эти методы позволяют пользователю сохранять любую информацию, предоставляя возможность создавать группы записей с иерархической структурой.

Загузка/сохранение осуществляется с помощью класса TextBlock.

Примеры

Пример способа с атрибутом:

class MyEntity : Entity
{
    [FieldSerialize]
    int someNumber;
 
    [FieldSerialize]
    Entity someEntity;
 
    // Здесь специально указывается имя, чтобы обфускатор не переименовал имя поля.
    [FieldSerialize( "someVector" )]]
    Vec3 someVector;
 
    [FieldSerialize]
    List<Entity> someEntityList;
}

Пример сериализации списка структур с помощью атрибута:

class MyEntity : Entity
{
    public class Item
    {
        [FieldSerialize]
        string stringValue = "";
 
        [FieldSerialize]
        EntityType entityTypeValue = "";
 
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
 
        public EntityType EntityTypeValue
        {
            get { return entityTypeValue; }
            set { entityTypeValue = value; }
        }
    }
 
    [FieldSerialize]
    List<Item> items = new List<Item>();
}

Пример способа с методами OnLoad/OnSave:

class MyEntity : Entity
{
    int someNumber;
 
    protected override bool OnLoad( TextBlock block )
    {
        if( block.IsAttributeExist( "someNumber" ) )
            someNumber = int.Parse( block.GetAttribute( "someNumber" ) );
 
        return base.OnLoad( block );
    }
 
    protected override bool OnSave( TextBlock block )
    {
        if( someNumber != 0 )
            block.SetAttribute( "someNumber", someNumber.ToString() );
 
        return base.OnSave( block );
    }
}

Пример сериализации игрового объекта с помощью методов OnLoad/OnSave:

class MyEntity : Entity
{
    Entity someEntity;
 
    protected override bool OnLoad( TextBlock block )
    {
        if( block.IsAttributeExist( "someEntity" ) )
        {
            uint serializedUIN = uint.Parse( block.GetAttribute( "someEntity" ) );
            someEntity = Entities.Instance.GetLoadingEntityBySerializedUIN( serializedUIN );
        }
 
        return base.OnLoad( block );
    }
 
    protected override bool OnSave( TextBlock block )
    {
        if( someEntity != null )
            block.SetAttribute( "someEntity", someEntity.UIN.ToString() );
 
        return base.OnSave( block );
    }
}

API

Класс EntityType

Имя Описание
ProtectedMethod.gif VirtualMember.gif bool OnLoad( TextBlock block ) Метод, вызываемый при загрузке типа игрового объекта.
ProtectedMethod.gif VirtualMember.gif void OnSave( TextBlock block ) Метод, вызываемый при сохранении типа игрового объекта.

Класс Entity

Имя Описание
ProtectedMethod.gif VirtualMember.gif bool OnLoad( TextBlock block ) Метод, вызываемый при загрузке игрового объекта.
ProtectedMethod.gif VirtualMember.gif void OnSave( TextBlock block ) Метод, вызываемый при сохранении объекта.