Documentation/Programming Articles/Entity System
From NeoAxis Engine Wiki
| Language: | Status: | Approved |
Contents |
Description
In this article you will examine the Entity System at programmer level. This article deals with the basic API entity system classes.
We recommend that you read the Introduction to Game Object System article before reading this one.
Reading the Tutorial in class creation would also be of use.
Basic classes of the Game object system include:
- Entity – The class of game object copy in the game world (game object class). You can edit class properties in Map Editor.
- EntityType - Game object type class. You can access the properties of this class through Game Objects Editor.
- Entities – Game object manager class. This one is used for creating new objects, working with object systems etc.
- EntitySystemWorld – A class for general management of entity system
You can find the code of the game object system in the EntitySystem.dll assembly.
Game objects system structure
All game objects form a tree-like structure growing from the World class object. Every object (except for the root one) can have parent and child classes.
Game object world is a hierarchy ascending from the World class object. Each object (except for World) has a parent object.
Currently the world hierarchy looks like the following:
Creating/removing objects
Creating objects
In order to create a new object you have to follow these steps:
- Create a new object by calling the Entities.Create() method.
- Adjust secondary properties (e.g. object location).
- Finally, call the PostCreate() method to add the object to the game world (thus making the object initialized).
Creation of a box on the map:
MapObject obj = (MapObject)Entities.Instance.Create( "Box", Map.Instance ); obj.Position = new Vec3( 0, 0, 10 ); obj.PostCreate();
Virtual methods and events call order while creating a new object
Various virtual methods and events are called during object creation. You can override these methods as well as add new functions.
Methods and events call order while creating a new object:
Methods and events call order while loading an object:
Notice: The OnCreate() method and the Create event are only called while creating a new object (and never during new object load).
Object Deletion
The standard object deletion is implemented by means of the SetShouldDelete() method.
E.g.:
MapObject obj = ...; obj.SetShouldDelete();
You can also use SetShouldDelete() or SetDeleted() methods to remove an object.
The difference between these two methods is that with the SetShouldDelete() method you can delay object removal for a certain period of time. This can be of use while creating game logic. Object removal delay is implemented by means of overriding the OnShouldDelete() virtual method. The SetDeleted() method removes the object instantly. It is better to use the SetShouldDelete() method as it allows the object to perform all the necessary actions before removal.
Demo-specific features: In SDK use the Die() method for Dynamic classes.
Virtual methods and events call order while removing an object
Notice that calling the OnShouldDelete() method can delay object removal for a certain amount of time.
API
Entities class
| Name | Description | |
|---|---|---|
| |
Entity Create( EntityType type, Entity parent ) | Creation of a new object of the specified type. |
| |
Entity Create( String typeName, Entity parent ) | Creation of a game object of the specified type name. |
| |
CreateEntity | An event called while creating a new game object. |
| |
DeleteEntity | An event called while removing a game object. |
Entity class
| Name | Description | |
|---|---|---|
| |
void PostCreate() | A method that adds the object to the game world. This one is called after game object parameters were specified. |
| |
void OnPreCreate() | A method called immediately after object creation. |
| |
void OnCreate() | A method called after object creation in the game world. This method is not called if the object is loaded. |
| |
Create | An event called after object creation in the game world. This event is not called if the object is loaded. |
| |
PostCreated | An event called as the object is added to the game world. |
| |
void OnPostCreate( Boolean loaded ) | A method called as the object is added to the game world. |
| |
void OnPostCreate2( Boolean loaded ) | A method called after the object was added to the game world. This method is called after the OnPostCreate method. |
| |
bool IsPostCreated | This property returns True if the object was created and added to the game world. Otherwise it returns False. |
| |
void SetShouldDelete() | A method informing that the object should be removed. |
| |
bool OnShouldDelete() | A method called during the SetShouldDelete method call. |
| |
void SetDeleted() | Removes an object from the game world. |
| |
void OnDestroy() | A method called after the object was removed from the game world. |
| |
Destroying | An event called before object removal from the game world. |
Object naming
Description
Every game object has its name accessible through the Name property.
Every object’s name is unique. A newly created game object is given a name of the following form {game type name}_{unique number}.
The name can be empty if the EntityType.AllowEmptyName property of the game object type is set to True. You can adjust this property while editing the game type in Game Objects Editor.
API
EntityType class
| Name | Description | |
|---|---|---|
| |
Boolean AllowEmptyName | Sets and returns the value enabling game object’s null name. |
Entity class
| Name | Description | |
|---|---|---|
| |
void OnNameChange() | A method called on object name change. |
| |
string Name | Object name. |
| |
NameChanged | An event called on object name change. |
Entities class
| Name | Description | |
|---|---|---|
| |
Entity GetByName( String name ) | A method returning game object by its name. |
| |
string GetUniqueName( String prefix ) | A method returning the generated unique name with prefix. |
Ticks and Timers
Description
The game world is simulated in certain time intervals. By default there are 30 ticks per second. Game object are notified about ticks when the simulation is on.
Any game object can be notified about game world ticks. To do this an object should subscribe to tick notification. This is necessary for the purpose of increased performance. Since timer counters are not serialized you have to restore subscriptions them after project load.
You can change the number of ticks per second in the "Definitions/EntitySystem.config" file, but it is not recommended.
Example
An example of a subscription to timer events and tick notification:
class MyEntity : Entity { protected override void OnPostCreate( bool loaded ) { base.OnPostCreate( loaded ); AddTimer(); } protected override void OnTick() { base.OnTick(); float delta = TickDelta; ... } }
API
Entity class
| Name | Description | |
|---|---|---|
| |
void AddTimer() | Increase of timer events subscription number. |
| |
void RemoveTimer() | Decrease of timer events subscription number. |
| |
void Client_OnTick() | A method called on every tick in the application. Is only available in network mode for client. |
| |
Tick | An event called on every tick. |
| |
float TickDelta | A constant equal to the time period between ticks (by default it is set to 1/30) |
EntitySystemWorld class
| Name | Description | |
|---|---|---|
| |
Boolean Simulation | Stops or continues simulation. |
| |
Single GameFPS | Returns a constant equal to the tick number per minute (by default it is equal to 30 ticks per second). |
Relationships (Object removal notification)
Description
The Relationship System enables notification on object removal. This can be used if it is necessary to notify one game object that other game object was removed.
You can establish relationship between two game objects so that each will be notified of another object’s removal (a virtual method will be called). This link is symmetrical and no object is principal or child.
This relationship does serialize, so you do not have to restore it on load.
Example
Below you will see an example of relationship creation and removal notification processing:
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 class
| Name | Description | |
|---|---|---|
| |
void AddRelationship( Entity entity ) | Relationship creation. Object will be notified on the removal of the related object (the OnRelatedEntityDelete virtual method will be called). |
| |
void RemoveRelationship( Entity entity ) | Relationship removal. |
| |
void OnRelationshipAdd( Entity entity ) | A method called while adding a relationship to the object. |
| |
void OnRelationshipRemove( Entity entity ) | A method called while removing a relationship from the object. |
| |
void OnRelatedEntityDelete( Entity entity ) | A method called on related object’s removal. |
| |
RelatedEntityDelete | An event called on related object’s removal |
Object serialization
Description
The serialization system is used for saving the map or the world. The serialization involves saving object (or object type) variables to recover them further.
There are two types of specialization:
- Game object type specialization (save and load of ".type" files).
- Game object specialization (save and load of the game world and the map).
The both types have similar syntax. Below you will learn about the serialization of both types.
There two ways to serialize a variable:
- Using FieldSerializeAttribute attribute.
- Using OnLoad()/OnSave() methods.
“Attribute” way
Attribute serialization is easier to use, however it has a limited functionality. You can use it to save almost any type (basic .NET types, game objects, game object types, lists and arrays), however it is inappropriate for saving irregular data.
The list of supported types includes:
- Simple types: bool, sbyte, byte, short, ushort, char, int, uint, long, ulong, float, double.
- STRUCTURES: Vec2, Vec3, Vec4, Bounds, Range, ColorValue, SphereDir, Rect, Vec2i, Vec3i, Recti, Degree, Radian.
- Strings.
- Emunerations.
- Classes based on EntityType.
- Classes based on Entity.
- Structures and classes.
- Arrays( T[] ).
- Lists ( List<T> ).
OnLoad/OnSave serialization
You can also use OnLoad()/OnSave() method methods when “attribute” serialization proves to be insufficient. With these methods you can save any information grouping the data in hierarchical order.
Load and save are implemented using the TextBlock class.
Examples
Attribute use:
class MyEntity : Entity { [FieldSerialize] int someNumber; [FieldSerialize] Entity someEntity; // The name is given with a purpose of preventing the obfuscator from changing the name of the field. [FieldSerialize( "someVector" )]] Vec3 someVector; [FieldSerialize] List<Entity> someEntityList; }
Serializing a classes list using the attribute:
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>(); }
Using OnLoad/OnSave methods:
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 ); } }
Game object serialization using 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 class
| Name | Description | |
|---|---|---|
| |
bool OnLoad( TextBlock block ) | A method called on game object type load. |
| |
void OnSave( TextBlock block ) | A method called on game object type save. |
Entity class
| Name | Description | |
|---|---|---|
| |
bool OnLoad( TextBlock block ) | A method called on game object load. |
| |
void OnSave( TextBlock block ) | A method called on game object save. |
