1
\$\begingroup\$

More often that not, when I see how item systems have been implemented in games, the items are retrieved using either a string or ID. Eg, GetItem("Sword") or GetItem(ID.Sword). Is there some advantage to this method that I am missing?

When I have made item systems in my games, I create a class for the item and get a new one that way - eg, new Item(Sword). At times I have also stored the items in a list of some kind, and retrieved them that way, eg GetItem(Sword).

So my question is - why do most of the systems I see use a name tag or id system? What's the problem with getting them directly by reference?

\$\endgroup\$
  • \$\begingroup\$ Why would you need to get them if you have a reference in the first place? \$\endgroup\$ – Bálint Aug 16 '16 at 11:21
  • \$\begingroup\$ First, strings are rarely the best solution for this because string comparison is often slower/uglier than integer or enum comparisons, and do not provide the guarantee of a valid value an enum gives. The reason ID systems are common is because it makes the save file format easy to write, unifies file names for assets, localization, and code, and because it works in non-object-oriented languages, like pure C or Assembly. \$\endgroup\$ – Groomblecom Aug 16 '16 at 11:49
  • \$\begingroup\$ Additionally to @Groomblecom , it's easier to compare two items by comparing their ID tag rather than comparing two objects. And by comparing, I mean checking if two items are the same or if you need to find out if an item is a sword or something. Also, ID tags make it easier to save game data or transmit it in the case of multiplayer games. \$\endgroup\$ – Nathaniel D. Hoffman Aug 16 '16 at 13:30
4
\$\begingroup\$

Both has advantages and disadvantages.

GetItem("HolySwordOfAwesomness") is more readable. But did you notice I misspelled "Awesomeness"? The compiler can't catch that error, so it will result in a runtime error which will need to be debugged.

GetItem(1337) won't throw a runtime error. It will create the wrong item instead. This bug might be even harder to catch than an explicit error. But the advantage is that this passes just 4 byte to the function instead of a 21 character string. Also, a lookup by integer can be implemented much faster than a lookup by string. So this method has performance advantages. But it is completely unreadable unless you have your whole item database in your head (you won't).

But you get the best of both worlds when you use integers, but also define a constant for each item: GetItem(ITEMID_HOLY_SWORD_OF_AWESOMNESS). This is readable, can be caught by the compiler because you are referring to an undefined identifier and it might offer you auto-complete help from your IDE. But the drawback is that you now need to define a constant for each item you create, which slightly increases the maintenance overhead for creating new items.

You can of course also go the object-oriented route and only refer to items by reference: player.GiveItem(new HolySwordOfAwesomeness()). But this only works as long as your game is completely contained within your program. References can not be passed via network, can not be read from a config file and can not be written to a savegame files. This means you will need some serialization/deserialization scheme for your items. Yes, some programming languages can serialize/deserialize objects to strings out-of-the-box, but most of these schemes tend to break after the slightest change to the class definition. IDs (no matter if integers or strings) make this much more convenient, robust and often far more compact. Also, the referencing approach can be difficult or impossible when you want to use a scripting engine (depending on the API for the engine).

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

In order to separate an engine from the game, you often referred to objects by a string. Especially in a scripted logic layer. Even if that name is hashed for an ID within the get method for optimization.

This way, script writers don't have to worry about how int based IDs might be changed from build to build after you learn that neither hardcoding IDs, nor looking up the ID you want from some intermediate manifest everytime are good options.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.