I'm making a 2D RPG. I have an "Entity" scene, a Node2D, which characters and objects in the game inherit from. Within each entity is an empty dictionary called vars, into which other nodes can easily store data, such as by adding a bool that marks the entity as having already been spoken to by the player.

I made a script that did exactly that, and instanced it in a child node of an NPC.

The script belonging to the child node:

the update_vars() method of the entity:

For some strange reason, though, it's adding that "spoken_to" bool into the vars dictionary of its parent entity, as it should, but also into that of every other entity on the map. When it updates its parent's "spoken_to" to true, it also does the same for every other entity.

So essentially, if I reuse this script in another NPC as well, if I speak to one, both will think they've already been spoken to.

Nothing else I do from this child script appears to be applying to every entity - just changing this particular dictionary. I can add print(entity.name), and it will only print its parent's name, as expected.

Does anyone have any idea what could be causing this? Have you ever had a line of script update a variable on a node and, erroneously, also on all of its siblings?

I'm sure I could find a simple way around this, but I want to understand why it is happening.

Edit:
Just did a little more science. The same issue occurs regardless of where the call to update the vars dictionary is coming from. It also applies to all entities on the map regardless of which YSort they're nested under - in other words, it's applying to every node that inherits from the Entity scene, not just the intended node and its siblings.

The issue also occurs regardless of whether the entry was added to the dictionary before runtime. In other words, if I add an entry to the dictionary in the entity script, and then have another script update it, the update occurs on every entity on the tree.

  • Dictionaries are copied by reference, so if you declare a variable in entity, outside of a method, and immediately assign a dictionary to it all objects will use the same dictionary. The quickest way around that is to assign the dictionary in _ready() or _init(). If that doesn't work, you'll have to show your entity script for more troubleshooting.

snowy-fox changed the title to Updating a Dictionary in a Node Applies to Node's Siblings Too .

Dictionaries are copied by reference, so if you declare a variable in entity, outside of a method, and immediately assign a dictionary to it all objects will use the same dictionary. The quickest way around that is to assign the dictionary in _ready() or _init(). If that doesn't work, you'll have to show your entity script for more troubleshooting.

    duane Ahh, so that's what the docs mean by "dictionaries are always passed by reference." I didn't know copy by value/copy by reference was a thing. Thanks a lot for that! I clearly still have a lot to learn about programming.

    Assigning the dictionary in _ready() worked. It's a bit of a shame, because as far as I can tell, that means you can't really export a dictionary in an instanced scene, since exported variables need to be typed to work. But, it still works for my purposes. It's just slightly less convenient.