Separating content from instance-specific data

Started by
1 comment, last by dendrite 8 years ago

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?

Advertisement

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.

Sean Middleditch – Game Systems Engineer – Join my team!

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.

This topic is closed to new replies.

Advertisement