use ID or Pointers

Started by
15 comments, last by Hodgman 7 years, 10 months ago

use ID or Pointers ?

texture ID, mesh ID, material ID, Entity ID?

or pointers,

or fileName? like test.png cube.obj...

which pattern is easy to maintain, I may store the data in the file. If use pointers to identify the resource , the pointers will differ when it reload from file.

Advertisement

If you're working in a team it's helpful to have ID numbers that stay the same across instances of your application. That allows people to share bug reports that clearly identify certain objects, to easily see in the debugger which object it is, etc.

I use handles for pretty much every resource that needs a direct link - I have different ways of managing them, but most of them are 32bit and store an index to an array of resources along with 8 bits or so reserved for a "magic" ID so I can track resource lifetime (i.e. if the resource is alive or freed). I think this might have been the first thing I read about it years ago: http://scottbilas.com/publications/gem-resmgr/. It's evolved since then but the premise is the same.

I tend to use hashes when serialising if one thing needs to look-up another. I've started to use a unique string index that's created at build time along with a dictionary (i.e. list) of all strings used. That can be used for compares + easy string lookup for tools and debugging, and saves having to keep the hash + string pointer around. However, it requires some additional management that i'm not sure is worth the pay-off yet.

T

use ID or Pointers ?

texture ID, mesh ID, material ID, Entity ID?

or pointers,

or fileName? like test.png cube.obj...

which pattern is easy to maintain, I may store the data in the file. If use pointers to identify the resource , the pointers will differ when it reload from file.

With the comment at the end it seems you already understand the trouble with pointers and persistence.

Pointers are the current, temporary, transitory location in memory. They make sense when you are referring to such temporary transitory things in your code, but rarely make sense anywhere else.

While they add an indirection and therefore add a minuscule performance penalty, handles or IDs or similar open up a wide range of solutions to applications. However, they take some time and effort to implement.

Tools that generated unique IDs for all game objects and then abstract away the links between models, textures, and scripts can work great. This allows for in-game streaming of assets, unloading them and reloading them as needed and using proxy objects when they are unloaded. IDs allow for persistence that you can (if implemented) handle assorted problems common during development where objects change or are updated or need to be corrected in some way. IDs allow for serialization between machines if you have networked systems. ID based systems can make it easy to dynamically reload the underlying assets when they change, giving easier development. IDs allow for many other fun and wonderful features once you pay their development cost.

This post, and its accompanying comment thread, may be of interest.
http://bitsquid.blogspot.com/2010/10/static-hash-values.html?m=1
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
I personally don't use one or the other, all times.
In some cases an ID doesn't fit my needs and/or the need to be able to do something with an object, without having the pointer. This might also be a design thing/flaw, but basically I think ID's are good, make sure you manage them well yourself, to prevent non existing ID's and nasty bugs because of this.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

If you want to serialise data and send it across a network, then you should consider ids and names as pointers can't be sent to different systems.

Don't use names in performance sensitive code as you'll need something like a hash map at best to store lookups of name to object, and this is slower than a simple pointer.

Last time I did this I built ids for each resource at compile time which was a simple crc 64 of each file name and used that as a constant 64 bit id value within the code to reference the object. I then used sparse arrays to contain the lookup.

Hope this helps!

You also do not have to use eigther - or. There is nothing wrong with having a pointer in your code, and when its about to be serialized, you can convert the pointer to an ID (for example via lookup). On deserialization, you perform another lookup to see which pointer to get from this ID.

I'm not saying that its the best option, but it certainly is a thing to consider. It still keeps the speed of pointers (in case you need the last inch of performance) and relative easeness for debugging (inspecting an object via handle in debugger can be more difficult), while being able to safely serialize/deserialize where needed.

i use arrays of structs as memory pools, and use the array indexes for the IDs. to load or save, all i have to do is read or write the array - no pointer fixups required at all - just load'n'go.

i use memory pools and IDs for:

static mesh assets, skinned mesh assets, texture assets, material assets, WAV assets, player entity instances, non-player entity instances, NPC instances, action types, object types, skill types, quest types, quest instances, and probably a few other things that don't come to mind at the moment. they all use IDs. quest types are the only thing that doesn't use a memory pool as well - quest types are pretty much 100% code (init, run, get map marker locations, get treasure location, select quest, view quest - that kind of stuff).

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Pointers - most cases.

Smart pointers - resource ownership.

Integer handles (e.g. ID's) - con: no direct access. pro: actual storage mechanism is now abstract, so much more flexible. Supports relocation, defrag, serialization, networking, 'weak handles' (detect use after free) etc...

Offsets: con: requires strict memory management. pro: can be templated to work like pointers, can be smaller than pointers, can be serialized.

Perfect hashing: great for asset names - gets rid of strings from the engine. Basically a subset of integer handle methods.

This topic is closed to new replies.

Advertisement