Correct way to call parent node functions within child nodes, utilizing Godot's Node based design

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By McVities Chocolate

Hello,

I am currently working on a project that uses tilemaps to create a background on to which I have various Node2D based sprites that navigate the cells of the tilemap in a grid based fashion.

So for the grid scene the root node is just of type Node and I have a tilemap node whose children are the Node2D nodes that represent characters (arranged as instanced scenes). The Node2D sprite scenes have a Node2D node as the root node with either Area2D or KinematicBody2D as children (and also associated collisions and sprites as children). The root node extends Node2D.

To achieve grid based movement I use the Tilemap class functions world_to_map and map_to_world but I require their usage in the instanced Node2D scenes, so I have created a variable Grid using the onready keyword that is set to get_parent() and then I call the parent functions from the Node2D scenes using the dot operator - Grid.somefunc()

This method works fine when the root node script for the Node2D scene has it’s parent as the Tilemap node, but I also have a Node2D scene where the root node is a Node2D and the children are Node2D nodes that represent different enemy characters.

So I created a script in the root node that uses the get_parent() method from before and in the child node scripts I tried using onready var Grid = get_parent().Grid to retrieve the Grid variable from the root script. But this does not seem to work and in the child nodes it seems the Grid variable is Null. So I worked around this by using var Grid = get_parent().Grid in _ready() following a slight delay and this works. However, I am thinking I am definitely over-complicating things and I think there is a cleaner solution here?

For clarity:

Tilemap # Parent
   Node2D # Child of Tilemap, "interface" script here.
       Node2D # Child of Node2D, functional scripts are here

I come from a C and ASM background and relatively new to OOP and game dev, really enjoying Godot but I want to make sure I make correct use of the excellent Node based design!

Cheers.

There’s a few ways I can think of.

You could connect those nodes to a signal on the grid node that then, on _ready(), signals out a ref to itself. You’d want to connect this in the editor though

Grid code:

signal here_i_am(ref)

func _ready():
    emit_signal("here_i_am", self)

Sprite code:

var grid

func _on_grid_here_i_am(grid_ref):
    grid = grid_ref

But this doesn’t work for objects spawned during the game, as you need a reference to the signal-emitting object in order to connect to it. What I would do is to use a singleton to store the grid reference, and then have the objects pull it on _ready(). So for example:

Grid Code:

func _ready():
    global.grid_ref = self

Sprite Code:

var grid
func _ready():
    grid = global.grid_ref

You can read more about singletons here: Singletons (AutoLoad) — Godot Engine (3.2) documentation in English

denxi | 2020-04-17 23:08

Thanks, this seems like a viable solution. However, I found that using Grid.get_parent().get_parent()seems to work when using onready

EDIT After reading up on singletons, it seems the best approach - works a treat, cheers!

McVities Chocolate | 2020-04-18 16:38