Jump to content
  • Advertisement
Sign in to follow this  
nonanon

Game Engine design for many-typed many-copied entities

This topic is 916 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What I am looking for is some advice on possible implementations of a game engine that is able to handle many (100+) different entity types (e.g. Wrenches, Clothes, Wall segments, Grilles, Chairs, etc. etc.) and also efficiently allocate resources for many instances of that entity (50+).

 

Some context: I am programming a 2D tile-based map where each tile can hold a certain number of items with which the player can interact. Each entity has some properties which can be shared (e.g. a wrench and a cigarette can both be picked up) but differ in many other ways, and some entities can be interacted with whilst still on a tile (chairs can be sat upon, items placed on tables...).

I have looked into entity component systems and have tried looking at an implementation that would work, but the problems i would need to overcome to make such a system usable are:

  • Per entity type data needs to be retained and not stored on each instance of that entity type (every single chair entity should not need to store a reference to it's texture, or a component stating that it can be wrenched to the floor)
  • Actions that aren't greatly suited to the use of systems and better suited to a reactional/event based design (drinking, welding...)

So do any of you have suggestions for either ways to fix the above problems or alternative architectures that work better in these circumstances?

 

UPDATE:

Thank you for your contributions. A post below by me details the chosen implementation based on the answers above it that I deem satisfactory for the requirements of the game.

Edited by nonanon

Share this post


Link to post
Share on other sites
Advertisement

Per entity type data needs to be retained and not stored on each instance of that entity type (every single chair entity should not need to store a reference to it's texture, or a component stating that it can be wrenched to the floor)

 

That's a strange requirement to have. That suggests to be like you plan on having code like

if (type == Chair)
{
    do this...
}
else if (type == Clothes)
{
    do this...
}
else ....

If, as you say, you plan on having 100+ types of entities, that kind of coding is just doesn't scale and will be a maintenance mess.

 

Or, if this requirement is just to save space, then you can just have a field in a component that references a descriptor for that object that contains its static properties.

 

 

 


Actions that aren't greatly suited to the use of systems and better suited to a reactional/event based design (drinking, welding...)

 

Using an entity component system doesn't mean you need to use it *everywhere*, and it doesn't mean you can't mix it with other types of designs. There's nothing preventing you from supporting generic behaviors/scripts that can be attached to entities to perform actions or respond to events.

Edited by phil_t

Share this post


Link to post
Share on other sites


Per entity type data needs to be retained and not stored on each instance of that entity type (every single chair entity should not need to store a reference to it's texture, or a component stating that it can be wrenched to the floor)

 

I'm not really sure what this issue here is about.  It sounds like you need a template/blueprint/prefab system, which isn't really at odds with an Entity system.  All blue chairs have a texture component, which has a reference to the blue material.  That material should be shared, so they're not all loading the same blue texture, sure, but they all still need to reference the texture (smart pointers as a simple example)  Or maybe you're referring to shared data of a more basic sort, like I dunno, starting hitpoints on a goblin.  But then they should all be referring to the same goblin blueprint/prefab/template, but would still have hitpoint components on each instance.

Share this post


Link to post
Share on other sites


Per entity type data needs to be retained and not stored on each instance of that entity type

 

relational databases is the traditional solution to this.   you have a list of entity_types, and a second list of entity_instances.  each entity_instance has a member variable called entity_type, which is what type of entity it is.

 

the entity_types list contains type specific constant info such as max hit points, turn speed, drawing info, etc. the entity_instances list contains variable entity specific info like current damage level of a given entity, its location and orientation, etc.

 


Actions that aren't greatly suited to the use of systems and better suited to a reactional/event based design (drinking, welding...)

 

actions are a different sort of beast from objects.. actions have a means of being triggered. they often have pre-requisites which must be checked. they often have a duration and chance of success, and results on success and failure. they can also have animations and sfx's associated with them. and stat and skill bonuses apply to actions.

Share this post


Link to post
Share on other sites


What I am looking for is some advice on possible implementations of a game engine that is able to handle many (100+) different entity types (e.g. Wrenches, Clothes, Wall segments, Grilles, Chairs, etc. etc.) and also efficiently allocate resources for many instances of that entity (50+).
5000 entities then? Thats nothing. Anything will work fine with that, unless you do something terribly wrong of course.

 

Also if say, a chair is something static, and a wall is static, its not a different entity. They're the same static kind of entity, with different textures. I very much doubt you'll have that many different kind of entities.

 

A game like Skyrim was made with probably less than 100 different kinds of entities (npcs, quests, statics, animated, weapon, armor, spell, and a couple more, thats it). Yours wont have as many as you think.

Share this post


Link to post
Share on other sites

There is an article in the first Game Programming Gems book called "Data Driven Design", and has a section about avoiding data duplication. I suggest reading it! The particularly useful idea is to use data inheritance. The example from the book looks like:
 

Goblin
{
	speed = 10
	life = 20
	attack = 15
}

Fast Goblin : References Goblin
{
	speed = 20
}

Instance : Goblin
{
	position = (5, 0, 0)
	Facing = (1, 0, 0)
}

The nice thing about the diagram the explanation differences between type definitions and type instances. Definitions can reference/inherit one another, and instances fill in the fields. In the context of some kind of aggregation/component system data files can be used to describe an aggregate (i.e. the Goblin has X Y and Z components), the fast goblin data file can reference the Goblin file, and modify some attributes or add/subtract components. An instance fills in the memory of the components.

Edited by Randy Gaul

Share this post


Link to post
Share on other sites


Per entity type data needs to be retained and not stored on each instance of that entity type (every single chair entity should not need to store a reference to it's texture or a component stating that it can be wrenched to the floor)

This shouldn't be an issue. Implement a new component which includes functions implementing the use of per-entity-type data. You can subclass the component as needed for more complex objects. Tiles, and perhaps even the entire gameworld, could be implemented as entities this way.


Actions that aren't greatly suited to the use of systems and better suited to a reactional/event based design (drinking, welding...)

Again, just create a component for each specific type of behavior you need. You can create an AI component, a decaying corpse component, etc.

You can wrap every piece of code you could ever write for a game in a component if you wanted, not just in-game objects.

Share this post


Link to post
Share on other sites

Thank you for your contributions. After reviewing the problem with the help of your replies i have decided to try a more general component-based solutions where what would usually be an entity is instead an entity type (which i like to call a behaviour), and each instance of that type is stored as a singe element of a vector within that entity type. That is to say (very, very simply):

Behaviour
{
    addComponent( Component* com )
    removeComponent( unsigned int comType )

    Component* getComponent( unsigned int comType ) 
};

TextureComponent
{
    textureid getTexture()
}

UsableComponent
{
    Script onUse( Id id )
}

ChairBehaviour : Behaviour
{
    Chair
    {
        int     direction
        Player* occupied
    }

    ChairBehaviour()
    {
        TextureComponent tComp = createTextureComponent( "chair.png" )
        UsableComponent uComp = createUsableComponent( "sit.script", [](Id id){ return this->chairs[id]->occupied } )
        addComponent( tComp )
        addComponent( new UsableComponent )
    }

    Chair  chairs[]
}

This adds a layer between the systems and individual items/objects that can be used to insert data that does not need to be stored in every object. Now the texture reference and script references just need to be stored in the chairbehaviour, of which there will only ever be one, and as you can see only the direction which the chair faces and the id of anyone sitting in it (null if empty) is stored for each chair on the map.

 

As I am programming in C++ which requires strictly typed variables and functions, some components (e.g. the texturecomponent) can store function pointers which are filled by the Behaviour so that a system (e.g. graphics system) only needs to know about that one component to retrieve necessary information.

 

Thank you for your help.

Edited by nonanon

Share this post


Link to post
Share on other sites

Entity component systems do not do well with projects of greater complexity.


What problems have you encountered (or do you foresee) using ECS architectures on complex game projects?
Are the problems you encountered merely from how you implemented your ECS, or are they inherent in all ECS architectures?

Per entity type data needs to be retained and not stored on each instance of that entity type (every single chair entity should not need to store a reference to it's texture, or a component stating that it can be wrenched to the floor)


What's wrong with storing a reference to a texture? Your graphics component needs to do that anyway, and you might have ten or twenty different chairs (several couches, benches, window seats, wooden chairs, computer chairs, etc...).

Actions that aren't greatly suited to the use of systems and better suited to a reactional/event based design (drinking, welding...)


Games are complex things, and you aren't required to cram every part of your game into a single paradigm. GUIs, for example, are recognized as poor fits for ECS, so for the GUI part of a game engine, you don't use an ECS, even if you are using ECS for other areas.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!