Sign in to follow this  
dendrite

Separating content from instance-specific data

Recommended Posts

In games, i wanted to allow the use of templates (which define the components an entity has, but instances of these templates may have different properties; e.g 2 fighters may have  position and velocity components but 2 fighters would have different values for both. They'd probably share some common traits like hull integrety, damage, etc).

My first thought to instantiating these templates was cloning all the variables, but there's an alternative i'm considering.

The data for entities can be divided into the following:
1. data that was defined from templates, and
2. instance specific data

I'd like to only save instance-specific data as I can think of several benefits to doing so:
1. More robust save files that allow you to make changes, while allowing instanced data to persist. For example, if you change the base stats of an item and have item customizations as instanced data then updating the base stats in a future update will also preserve the customizations made.
2. Less memory usage as all instantiations of a template can share data from its template but have instance specific data

So for our example, these 2 fighters would share damage and hull integrety data, while maintaining their instance-specific position and velocity component data.

Anyone has ideas on how i could implement something like this?

Share this post


Link to post
Share on other sites

There's dozens of ways. A common one is to just have your components have an embedded ref-counted pointer to "template" data that is copied when an object is instantiated, roughly implementing the "flyweight" pattern.

// psuedo C++
class MyComponent {
  shared_ptr<TemplateData> data;
 
  void Load() {
    data = make_shared<TemplateData>();
    data->foo = load_foo();
    data->bar = load_bar();
  }
 
  MyComponent* Clone() {
     // this will copy the `data` pointer and add a reference, not copy all the data
     return new MyComponent(*this);
  }
 
  bar GetBar() const {
    return data->bar;
  }
 
  foo GetFoo() const {
    return data->foo;
  }
};

There are many other ways of achieving your goal if that one doesn't sit well with you for some reason. You'll need to more clearly state your requirements if there's something specific you'd want an implementation to do or to avoid doing.

Share this post


Link to post
Share on other sites

Ah, sorry. Should have stated more explicitly what my question was.

Is what i'm trying to achieve done often?

All read-only access to the entity's info can just return information from the template.

For instanced data, it seems like a lot of code would be required. For e.g,

class Entity {
TemplatePtr shared;

// variables that can be changed on per instance basis
PositionPtr pos = nullptr;
VelocityPtr vel = nullptr;

// if non-const access is required and if we don't have a copy of the component for this instance, make a copy and return it (i.e, copy on a potential write)
Position getPos() {
return pos = nullptr? pos = new Position(shared.getPosition()) : pos;
}
// and similarly for velocity

// const version that returns the instance specific copy if it exists, or the shared one otherwise
Position getPos() const {
return pos = nullptr? shared.getPosition() : pos;
}
};

Is there some way involving c++ templates i could use so that i could just have 2 functions templated on the component type, a const and non-const version? I don't want to have to write 2 functions per component type.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this