Can node A inherit position of node B without becoming a child of that node?

Godot Version

4.2.2

Question

I’m learning Godot by making a top-down 2D game that’s very much like Pacman except with trains. Player is being chased by enemies (all CharacterBody2D) and everyone can board trains (Area2D following a Path2D) to get around the game area faster.

When a character boards a train, I want them to move in sync with the train (as in, actually stay on it instead of being left behind), but also to be able to move WITHIN the train (as in, go from the back to the front etc). This is easily achieved if I set the player and enemies to be children of the train. However, the characters will be boarding and leaving different trains frequently, so I’d have to keep reparenting them constantly. Correct me if I’m wrong but that doesn’t seem like a scalable solution to me.

So far I tried using the RemoteTransform2D node. When using global coordinates, that node manages to move the characters together with the train but it also makes them “stuck” and unable to move away from the RemoteTransform position at all while the train is moving. When using local coordinates, the RemoteTransform node doesn’t seem to do anything…

Is there another way to make a the characters have their position modified by the train node without having to reparent them as children of that specific train? I tried making a custom script by that keeps track of the global positions of the character and the train but it’s kind of cumbersome and doesn’t work as well as just reparenting. I feel like I’m missing something. If you know a simpler way to do it, I’d be really grateful!

Okay, I think I solved it using dynamically repositioned marker nodes - here is my somewhat hacky solution in case anyone stumbles on this thread while stuck on a similar problem.

Node Tree

World (Node2D)
| – Trainline (Node2D)
| – | – TrainStation1 (Area2D)
| – | – TrainStation2 (Area 2D)
| – | – TrainlineRoute (Path2D)
| – | – | – PathFollow2D
| – | – | – | – Train (Area2D)
| – | – | – | – | – PassengerPosition (Marker2D)
| – Player

Code in player.gd:

const speed = 100
var direction = Vector2

var inside_train = false
@onready var marker = $"../TrainLine/TrainlineRoute/PathFollow2D/Train/PassengerPosition"


func board_train():
	# when player boards train, Passenger Marker is placed at player position
	inside_train = true
	marker.global_position = global_position
	martker.global_rotation = global_rotation


func _physics_process(delta):
	# before moving, put player in the location of the passenger marker
	if inside_train == true:
  		global_position = marker.global_position
		# rotation needs updating or player will end up outside the train when train turns
		global_rotation = marker.global_rotation 

	# move player as normal
	velocity = direction * speed * delta
	move_and_slide()

	# after player moves, move the marker to the new player location
	if inside_train == true:
		marker.global_position = global_position
		marker.global_rotation = global_rotation

Notes:

  • The code needs to be made neater (e.g. without a hardcoded get_node reference to the marker node from the player script).
  • Each passenger will need their own Passenger Marker node to allow for individual movement.
  • Each Passenger Marker node could be instantiated dynamically when a character boards a train.
  • There might be a smarter way to achieve it using a similar method with RemoteTransform nodes but I really can’t see it right now.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.