Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | notanome |
Hi y’all!
I’m creating an inventory system. There are the ItemData, which are basically static, .tres resources describing a kind of item, like “wheat”, “flour”, etc… With properties like name, value, ingredients used to make it, icon, etc…
And then there are Items themselves - they store a reference to an ItemData and have an amount and are what is actually used in an inventory. This leads to accessing the properties of the data reference when dealing with items: item.ref.name
, item.ref.value
…
And so on. This concerns me because, ideally, external systems should not be worried about the internal makeup of the Item class and the mental hoops to change from ref to item caused some silly mistakes.
I thought of some possible solutions:
-
Item extends ItemRef, values are copied on _init.
This works but causes data duplication and sync issues. ie: if the ref.name changes, the item would be outdated. This would require updating the item on ref change, which seems… ugh. -
Item _get(property) points to ItemRef
Works but breaks autocompletion and is unsafe, due to the dynamic nature of it
func _get(property: String):
return ref.get(property)
- Item with same fields as ItemRef and a lot of setget
Works but is quite verbose. I mean:
var my_name : String setget noop, get_my_name
func noop(v):
return
func get_my_name():
return ref.my_name
I was wondering if anyone else has a better solution (or maybe even a different idea altogether!).
My mind immediately went to option 3. It encapsulates the implementation details while safely exposing internals in such a way that shouldn’t change during the development process. The only thing to be mindful of is using self.member
to access your member variables from inside the script in order to trigger the setters/getters (the need to do this is going away with godot 4).
Option 2 lends itself to spelling errors so that’s immediately out in my mind.
Option 1 really depends on what you plan on doing with it. It can be okay if the ref only stores things like max/min values, static names, description flavor text. It would be a poor choice for things that are constantly being updating e.g. quantity owned, durability.
item.ref.name
COULD be okay. (I use this when I would rather create a struct
in other languages and I don’t want to mock a struct
with a dictionary.) I’m not sure if resources will give you auto-completion of member variables from the editor if accessed in this manner. If they don’t you could always create your own class that extends Node
then give it class_name ItemData
. When create your reference variable in your script you just qualify it: var data : ItemData
and it should give you the auto-completion in the editor. I also use this style when I’m referencing something that makes sense in my head like player.CharacterSheet.strength
since it immediately makes sense for me in my head to think that a strength
variable would be in a player
’s CharacterSheet
.
timothybrentwood | 2021-08-19 03:31
I agree with your points! I was basically using the player.CharacterSheet.strength
style, but I would like external systems not to have to think about refs. It felt weird to type item.ref.value
instead of item.value
.
Godot 4 would make number 3 much less of a hassle with the new setget API (and typed arrays, for when dealing with many items).
notanome | 2021-08-19 14:20