Random Spawn path following player movement

Godot Version 4.2.1

Hello!
Im trying to make a object spawn childs along a specific axis that changes based on where the player moves. Im figuring this out so I can make a simple platformer game where the path2d spawnline follows the players y axis.

The aim is that on the timer countdown, the random min/max .x spawning location changes based on player movement but it is currently remaining static.
In the scene tree for this test file the two marker2ds are children of the Player and follow the players movement automatically. When the test scene first instantiates it seems the var marker1/var marker2 variables are assigned the position.x of each marker AND the spawning does happen randomly along the interior of the two position.x of the marker2ds but when the player moves, bringing the marker2ds with it, the positions don’t update and the add_child continues to spawn in the marker2ds originally assigned position.

Do the variables not update on the timer countdown?

extends Node2D
@export var player_scene: PackedScene

Called when the node enters the scene tree for the first time.
func _ready():
$TestTimer.start()

Called every frame. ‘delta’ is the elapsed time since the previous frame.
func _process(delta):
pass

func _on_test_timer_timeout():
var marker1 = $CharacterBody2D/Marker2D.position.x
var marker2 = $CharacterBody2D/Marker2D2.position.x
var child = player_scene.instantiate()
var rand_marker_x = randf_range(min(marker1,marker2), max(marker1,marker2))

print(marker1, " marker1 “, marker2, " marker2”)
child.position.y = $CharacterBody2D/Marker2D.position.y
child.position.x = rand_marker_x
add_child(child)

Sorry in advance if I haven’t formatted this right, im on break at work and am very very new to all this.

A node’s position is relative to the position of its parent. If you want the absolute position, that is, relative to the origin at (0,0), use global_position instead!

That being said, your solution seems needlessly complex to me, when you could just as well do it like this:

func _on_test_timer_timeout():
    var child = player_scene.instantiate()
    child.global_position.x = $CharacterBody2D.global_position + randf_range(100, 100)
    add_child(child)
2 Likes

Replacing position with global_position would work, or adding $CharacterBody2D’s position to the child.

side note formatting code is done with three ticks

```
extend Node

var my_var = 1
```

extend Node

var my_var = 1
2 Likes

This code does seem simpler thank you and is partially working after changing it to

func _on_test_timer_timeout():
	var child = player_scene.instantiate()
	child.global_position.x = $CharacterBody2D.global_position.x + randf_range(-100, 100)
	add_child(child)

Edited the randf_range to -100, 100 instead of 100, 100 and added a .x to $CharacterBody2d.global_position. When I ran it as written originally it returned the error “Invalid operands ‘Vector2’ and ‘float’ in operator ‘+’.” I think thats caused by trying to change the .x value of child.global_position with a non .x value? Is that right? The 100, 100 randf_range was also giving a static +100 because the range is actually zero numbers between 100 and 100. Is that right?

With these quick changes I am still running in to a problem where the instanced object spawns to the right of the $characterBody2D, please see attached image.

Thanks for the script snippet it is way more sensible!

1 Like

Your edits are correct, maybe the character’s sprite2D isn’t at (0, 0)? of course make sure the distance between the markers is 200px since that’s the range set by randf_range

2 Likes

So changing the position to global_position has worked also with the code:

func _on_test_timer_timeout():
	var marker1 = $CharacterBody2D/Marker2D.global_position.x
	var marker2 = $CharacterBody2D/Marker2D2.global_position.x
	var child = player_scene.instantiate()
	var rand_marker_x = randf_range(min(marker1,marker2), max(marker1,marker2))

	print(marker1," marker1 ",  marker2, "marker2")
	child.position.y = $CharacterBody2D/Marker2D.position.y
	child.position.x = rand_marker_x
	add_child(child)

The reason why it was needlessly complicated is because im still trying to understand how the code actually works. The marker2d vars were being printed to the log so I could monitor if they actually changed their position which they werent doing.

They DO change now when the script is global_position.x instead of position and the instance’s spawning location is moving but I still have the issue where it is now spawning outside of the marker location randf_range.

Does it have anything to do with me having manually placed the other nodes? I cant think of why it’s spawning outside of what I expect the spawn range to actually be.

Thanks for taking the time to reply! This is a lot of fun.

This is how I have set up the scene tree by manually placing the node.

This is the wrong thing to do isnt it? Does doing this throw of the x.y value of the node in some way?

Perfectly fine to use markers! It’s a great way to visualize as long as the visual is correct. Make sure all of your Sprite2D child nodes are offset by 0, 0 in the inspector, I might be good to group them so you don’t accidentally move the sprite instead of the markers.

Also double check your player_scene that is being spawned, make sure it’s children are at (0, 0)

1 Like