The primary issue is that many objects need to reference each other, and they need to store these references. The issue here is when an object dies, how to cleanup all these references (e.g. incoming projects might have a target reference to it, whatever unit was attacking it, a unit it was attacking might have stored an attackedBy reference, etc).
The only solution I could think of was to make break away from the idea that an object is deleted at the point it is destroyed.
- Make the objects reference counted, to prevent deletion while still referenced by somthing.
- Have a kill() method that is called when the unit is killed. This nulls out all references to other objects, and sets the alive flag to false.
- Have an isAlive() method for other objects to use to see if the object they are referencing is still alive. If not, they should release that reference and carry on (e.g. attempt to find somthing else to shoot at instead)
This seems perfectly viable to me. However I get the impression from a number of bits of code Ive seen around or people have talked about that this is not actually how the problem is generally solved. However I can't personally see another solution that doesnt involve essentially reference counting every object in the game world. Is there another way? I guess there is also a performance impact (not really worked out how many references get aquired/releashed per update step yet)?
[source lang="cpp"]
class WorldObject : public MakeRefCountedSomehow
{
public:
WorldObject():alive(true){}
virtual ~WorldObject()
{
assert(!alive);
}
bool isAlive()const {return alive;}
virtual void kill()
{
alive = false;
};
private:
bool alive;
};
class Unit : public WorldObject//likly some other classes inbetween
{
public:
virtual void kill()
{
target = 0;
WorldObject::kill();
};
private:
ref_ptr<Unit> target;
bool alive;
...other stuff...
};
[/source]
On an implementation note and not reinventing the wheel. I never really liked shared_ptr with how it adds reference counting to a class that is otherwise not reference counted. There is intrusive_ptr, but is there existing and tested code for the reference counter itself (put somthing together with interlocked increment/decrement and initial ref count of 1 already if not)?