References to other objects: Pointers or ID's?

Started by
17 comments, last by Matt_D 14 years, 10 months ago
Game objects need to know about other game objects or lists of game objects. I tend to store those as pointers (C++) for ease of use. HOWEVER, i've been doing a lot more webdev and database work professionally than i do gamedev work at home. In a database-heavy environment (like a web app), you tend to store everything as an ID number or some other lookup identifyer. The nice thing about ID's is that you don't have to worry about memory issues or about directly possesing a reference to the object. You just need a way to find it (an ID number). Does this ID-lookup approach work well for games? In particular, I'm thinking about a networked TBS game. There would naturally be a lot of game objects to pass around and different machines need a way to address these objects in a way that doesn't involve memory addresses. Does anybody else tend to use this approach? Anything positive or negative to say about it? Thanks for your input. Much appreciated!
Advertisement
The only time ive ever used an ID approach is with OpenGL when binding a texture. Or some awful hack to get the player you know is stored at X position in a vector. I prefer storing pointers and references but i can't really see a downside to your method.
Quote:Original post by leiavoia
HOWEVER, i've been doing a lot more webdev and database work professionally than i do gamedev work at home. In a database-heavy environment (like a web app), you tend to store everything as an ID number or some other lookup identifyer.

Yes. In order that SQL work with a wide range of technologies, it's important that entities be referred to by integers, rather than by more low-level identifiers.
Quote:The nice thing about ID's is that you don't have to worry about memory issues or about directly possesing a reference to the object.
IDs work better than pointers at identifying objects that may move in memory or may not always be present in memory. This situation is almost assured when you're pulling data off a disk-backed database. It is less usual in C++, though by no means rare.
Quote:Does this ID-lookup approach work well for games?

On some occasions it is useful to have a handle class which allows the referencing of objects. This allows you to track visibility of objects, as well as to abstract away the process of locating (and possibly loading) them. shared_ptr is an example of this, as is HMODULE. Using integers for this purpose tends to confuse things, though it is quite common.
An alternative approach would be to use boost::shared_ptr and boost::weak_ptr (or other smart pointers); keep the master copy as a boost::shared_ptr, and pass copies of it as boost::weak_ptrs. As soon as the shared_ptr is destructed, the weak_ptrs will return a NULL pointer on an attempt to access the actual object (technically it returns an empty boost::shared_ptr, but it's basically the same thing). However, compared to the ID-lookup approach, serializing those pointers to disk may prove to be a challenge.
use both perhaps?
I always use IDs (for the reasons u mentioned) but if the ID is accessed very often I also store a pointer as well as the ID.
Sure, there are valid reasons why you might want to use integer identifiers rather direct pointers, design 'cleanness' just isn't one of them.

The ability to move objects in memory is one, serialization is another, and handling references to dead objects a third. However I would suggest that you only use indirect identifiers locally where such features are needed, not as a global abstraction layer for a core game component. Because the costs *will* add up.
Consider the cost of not being able to follow object pointers in the debugger, of having to pass around or reference a global object table whenever dereferencing an actor, of actually doing that (hash) table lookup to dereference an object, and so on. Seemingly insignificant things, like being able to eyeball pointers in a crash dump, can make a big difference when talking about a design choice that would affect half your code base.
ID"s every time.

- you can defrag your resource memory, and not worry about who's still holding what address
- you can, at runtime, change what data resides at what ID, allowing things such as re-skinning game elements to be seamless.
- it makes it easier to serialise
- it makes it easier to deal with multiprocessing, as you can generate multiple copies of resource data on a per thread basis.

yes, there is some performance penalty for looking up ID's, but on the whole, its makes for a much more flexable solution.
another alternative is to use a weak pointer, which has the same advantages but less lookup overhead. (and you can store both the ID, and the pointer, in the weak pointer object).
your never as good as they say you were, never as bad as they say you was.
Quote:Original post by Matt_D
ID"s every time.

- you can defrag your resource memory, and not worry about who's still holding what address
- you can, at runtime, change what data resides at what ID, allowing things such as re-skinning game elements to be seamless.
- it makes it easier to serialise
- it makes it easier to deal with multiprocessing, as you can generate multiple copies of resource data on a per thread basis.

yes, there is some performance penalty for looking up ID's, but on the whole, its makes for a much more flexable solution.
another alternative is to use a weak pointer, which has the same advantages but less lookup overhead. (and you can store both the ID, and the pointer, in the weak pointer object).


You can also use IDs that specify the object's position in an object list, so there is no performance hit. Player ID 3 is the Player object at playerList[3]. You have to pre-allocate space for the max number of each type of game object though.
Quote:Original post by EJH
You can also use IDs that specify the object's position in an object list, so there is no performance hit. Player ID 3 is the Player object at playerList[3]. You have to pre-allocate space for the max number of each type of game object though.


i think its worth noting that IMHO ID's should never be treat as indexes. ever. :)
use a lookup, and/or a hashing function, otherwise youll get into trouble :)
your never as good as they say you were, never as bad as they say you was.
yup. hash maps are your friend.

Everything is better with Metal.

This topic is closed to new replies.

Advertisement