How to access another data from another node/scene?

Godot Version

-Godot 4.2.1

Question

Hey everyone, I’m new to godot and I can’t figure out how to access data contained in another node/scene. Specifically, I’m trying to access the location of another node, so that I can move my enemy AI (a monster in this case) towards that other node. Here’s my script . . . movement_target is supposed to be accessing the MovementTarget node in the scene, but in the other parts of my code it returns “nil”, presumably because it doesn’t exist?? I’d be very grateful for any help I can get. How do I access the other node? I’m trying to access a Marker2D node, with a timer node as it’s child.

extends CharacterBody2D

enum {
    PATROL,
    CHASE,
    INVESTIGATE,
    ALERT,
}

@export var speed: int = 30
@export var slow_down_force: int = 100

var state = PATROL

@onready var target_axis
@onready var movement_target = $MovementTarget

@onready var alert_state_timer = $AlertStateTimer

func _ready():
    reset_target_axis()
    position = Vector2(250, 100)

    func _physics_process(delta):
        match state:
	        PATROL:
		        patrol_towards_movement_target()
	    CHASE:
		    pass
	    INVESTIGATE:
		    pass
	    ALERT:
		    pass

func reset_target_axis():
    if movement_target != null:
	    target_axis = movement_target.axis
    else:
	    print("No node found")

func patrol_towards_movement_target():
    position += (target_axis - position) / slow_down_force

func _on_body_entered(body):
    if body.is_in_group("Player"):
	    pass
    else:
	    reset_target_axis()
	    handle_movement_direction()
	    patrol_towards_movement_target()
	    print("collision occured")

use signal or callable

Signals don’t work in this case, unless I’m misunderstanding something. I need to have constant access to the other node’s location, and update the monster location accordingly. Is there such a thing as a signal that fires off constantly? Thanks for taking the time to respond!

then when creating the enemy, the enemy should be given that node/player reference and saved inside enemy’s variable to be used in the script

it is possible to emit signal constantly by emitting the signal at _physics_process or _process. but yeah depends what you wanted

This line of code:
@onready var movement_target = $MovementTarget
is storing a reference to my MovementTarget node, right?

the $MovementTarget, did you drag and drop it from scene tree or typed?

I typed it out.

then drag and drop it from scene
unless you cant because the target is on different scene

I have the target saved as it’s own .tscn file, but I have a world scene where all the tscn files have been placed to make up the level.

oh ok, so you put it all in, then you can just drag and drop then

I don’t instantiate the enemy, because they start in the scene? Instantiation confuses me a bit . . . do most ppl have an empty scene and instantiate a bunch of tscn files to populate it? Last time I tried to instantiate something, it created a copy of the object in the master scene, and I only wanted 1 of them.

But maybe that’s a whole different issue . . . I don’t want to take up all of your time. Thanks for the help!! I’ll have to look into it and see what works.

1 Like

when you need to generate lots of enemy or with level generator, it would be needed to instantiate and add_child from code. so dont need to put it one by one and save it into a scene

so the enemy shall follow the player if he sees the player?

if you want access a parent node and then access another node try this:

var marker = get_parent().get_node(“Marker2D”)

edit:

if you want to follow and unfollow the player i do it with an area2d. Then you can use the signals on area or body entered, same on exit. Thats how I do it

var player = null

func _on_body_entered(body):
if body.is_in_group(“Player”):
player = body

func _on_body_exit(body):
if body.is_in_group(“Player”):
player = null

func _update():
if(player != null):
position = position - player.position

I’m working on the enemy’s patrol state. I have another script attached to the Marker2D scene, which generates a random vector2d and places the marker2d node at that random vector location.

So now I’m trying to get the monster to move toward the Market2d scene/node tree. I had it as a child of the monster scene at one point, but it didn’t work because any time the monster moved, the Marker2d node moved too. I’d like to get the monster to the marker2d node, so i can fire off an event on collision and reset everything.

an option would be to seperate this:
take an empty 2d node and put the monster and the marker in the 2d node.
Now they can be moved seperated. you cat access the marker from the monster (I expect that the script is on the monster) with :

var marker = get_parent_().get_node(“Marker2d”) # now you can access on all proberties from the outside and the monster does his work alone.

Maybe you can send some pictures, to get an better expression.

1 Like

That’s a fantastic idea! Thank you so much. I just tried to implement it, and it seems to be working, for my purposes. So. Thank you.

1 Like