this is probably quite a beginner’s question, but the posts I’ve found don’t quite help. I guess I just have the wrong “mental model” of how things should work.
The following situation, I have a tree that looks like this:
player and enemy scenes look like this:
-Node2D (Attached script player.gd or enemy.gd)
–sprite2d
–…
Within arena.gd I get the child nodes with get_children (the instances of player.tscn and enemy.tscn). However, these nodes are of type Node2d. So I cannot access my methods.
So my question is:
What ways are there to access the methods of the attached scripts player.gd and enemy.gd without having to explicitly list the instances somewhere? Of course I could use signals, but as I understand it so far, I would have to explicitly call the instances of player and enemies in arena to connect the signals. That’s why I wanted to use the get_children approach, as I wouldn’t have to explicitly name the children here.
I found out for myself. Calling methods from subscenes works… The top node must also have the script attached in the subscene. I don’t know why they weren’t for me, because normally this happens automatically. So the tree should look like this:
-root (root.tscn)
-arena (node with attached script arena.gd)
-player (player.tscn with attached script player.gd)
-enemy (enemy.tscn with attached script enemy.gd)
-enemy (enemy.tscn with attached script enemy.gd)
player and enemy scenes look like this:
-Node2D (Attached script player.gd or enemy.gd)
-sprite2d
-…
on the first line, you can write class_name Player or class_name Enemy
inside your arena.gd, you can then initialize the child nodes as @export var player: Player and then assign the player scene to arena
your player node will now autocorrect all its specifically created methods
as script are usually attached to the scene, you can not just execute a method without having a reference of the scene, that’s why your solution is also dependent on get_children(). If your method functionality is general, you can create an autoload variable (maybe call it Global.gd) and then you can access Global.do_something() anywhere you want.
For example, Global.do_something(child) can be called regardless if child is an enemy or player. Useful for something like Global.highlight_character(node). You can also employ other solution that makes use of a Base_Unit class, which your Player and Enemy are inheriting from. That way, both share the same base methods that can be called by your arena.gd.
Example for Base_Class that has update_health() for Player+Enemy:
for child in get_children():
if child.has_method("update_health"):
child.update_health()
Lastly, when you instantiate player and enemy on run-time, you can then add them to specific groups. Afterwards, you are then able to loop through the group and then execute specific instructions/methods. That way, you don’t require a “hook” on the object or a variable, and you don’t require get_children() although it is quite similar in effect.