Advertisement

Game Entity System, flexible and good

Started by December 27, 2020 03:39 PM
4 comments, last by robvleugel 3 years, 11 months ago

Hello hello, I am currently working on platformer game and there is something I have problem with. I want to create flexible entity system that will allow me to create multiple types of enemys,tiles etc. The problem is there will be no only one difference between for example two enemys like just different HP or Sprite, I want to make a flying entity,walking entity,NPC, moving platform,solid platforms, so we talk here about also other kind of behaviour. I could create a class Entity and create next classes like Entity→Enemy→WalkingEnemy→Rat/Zombie etc. but its not good to have 2403 and half classes of different enemys. I could create MovementComponent/FlyingComponent and then assing them from a file, but I also think about something much more flexible like connect it with lua scripting, but I still have no idea thats is good, and event if it is how to generally do it. Its mean I know how to make a scripting part etc. but I have no idea about generall construction/pattern? If you guys can help me or give any tutorial,just something that would help me get out of this problem, I will aprecciate.

This question did not belong in the Writing forum. Accordingly, it has been moved to a more appropriate forum.

-- Tom Sloper -- sloperama.com

Advertisement

@Programmist94sealand

Hi there,

This depends on how much time you feel like putting into the game engine. The most common solution is to use the Entity-Component-System (ECS). The way this works is that every entity in your game consists of multiple components that define their behaviour through corresponding systems.

Entity → Every entity has a unique ID number. In some ECS implementations it is really nothing more then an integer.

Components → Data structures. Examples can be PositionComponent that stores the position of the entity, speed, acceleration or whatever you want to put it. Other components could be a SpriteComponent (storing the sprite, animations etc.)

Systems → These act upon the Components, its the place to add the functionality. You use the entityID to interact, E.g. PositionSystem::GetXPosition(int entityID); returns the X position of a certain entity or SpriteSystem::Animate(int entityID) would play the animation of a certain entity. The systems look for the data in the components, which are mapped to the entitiy ID's.

I use a factory to create new entities from XML files. In the example below I defined 2 different entities. Entity 1 has a sprite and position (x=50 y=50). Entity 2 has a different sprite, different position and in addition has a drag component that allows it to be dragged on the screen both horizontally or vertically. Now if I want to create these two entities I can just call EntityManager::CreateEntity("Entity1"); or to create 5 entities of the second one: EntityManager::CreateEntity("Entity2", 5);

You can further extend the functionality of your entities this way by creating more components/systems. Its also very reusable for other games compared to putting everything into large classes.

<Entities>

<Entity name="Entity1">

<PositionComponent>

<Arguments x="50" y="50" />

</PositionComponent>

<SpriteComponent>

<Arguments TextureID="sprite1" />

</SpriteComponent>

</Entity>

<Entity name="Entity2">

<SpriteComponent>

<Arguments TextureID="sprite2" />

</SpriteComponent>

<PositionComponent>

<Arguments x="1000" y="125" width="310" height="292" />

</PositionComponent>

<DragComponent>

<Arguments vertical_drag="true" horizontal_drag="true" />

</DragComponent>

</Entities>

For more information on ECS you should just use Google. E.g. https://austinmorlan.com/posts/entity_component_system/

There are situations that benefit from pure ECS, there are situations that benefit from pure OOP and there are situations when a mix of both could be appropriate. Everything is valid as long as it fits your needs, so if you feel that most entities would share some kind of properties, you are free to make them a base class and just keep the dynamic behavior in components.

I did this with our build tool. It contains a flexible pipeline that reacts to the data pushed to it. The clue is that there is no fixed behavior on how the pipeline behaves, so for example C# input data may be processed to a Visual Studio project solution or just be compiled. I was in the same situation here as you currently are, have tons of command messages to communicate with different parts of the pipeline. I then thought about a pure ECS solution which caused the code to increase for security code to ensure entities have components, add components, change component data etc. This wasn't the right solution either so I ended up with a mix of both, have fixed command inheritance where needed (like for common shared data) and everything else can be used in a flexible style of adding different components.

TL;DR: ECS is great, especially for games and tools that work with dynamic content but it isn't an all-or-nothing solution. The good about the job as a game developer is that there isn't 1 solution for everything ?

Ofcourse, all systems have their pros and cons. ECS is something I really enjoy using, but it takes quite some time to set up. Its especially useful if you plan on reusing the code for multiple other (larger) projects.

A bit more about how to do the scripting part. I use XML to define my entities, but using Lua is fine too. In that case you could create a Lua script file with parameters about your entities that are read by your entity construction class. Just like in my XML example you need a factory class to parse the script file and see what components are present and create all these components for the entity with the arguments provided in the script.

In my project I create 1 copy of every entity I define in my script files at load time, and then copy those entities if I need more of them. Going through the process of parsing the XML/Lua file every time you need a new entity is too time consuming.

This topic is closed to new replies.

Advertisement