Side scroller platform spawning

Godot Version

Godot V4.3

Question

1) Is it possible to spawn preset platform scenes from an Array without using Tilemaps? 2) How can I go about spawning them based on character position? Ive tried using a Marker2D attached to player to set spawn locations and come up with errors. All the procedural generation videos that ive seen do it with top-down and/ or Tilemaps. Here's a code I tried and had no luck with so far, is this the right idea or am I going about this way wrong?

extends Node2D

const L1 = preload("res://scenes/platforms1.tscn")
var spawn_pos = global_position
@onready var player = get_parent().get_node("Player")
const width = 80

func ready():
	pass

func process():
	
	if spawn_pos.distance_to(player.global_position) < 200:
		spawn_platform()
	
	pass

func spawn_platform():
	
	var spawn_l1 = L1.instantiate()
	add_child(spawn_l1)
	spawn_l1.global_position.x = spawn_pos.x
	spawn_pos.x= spawn_pos.x + width
	
	pass

This is the script on my PF spawner attached to my main scene like this.

Thanks in advance! :pray:

So, I got your code to work, all I changed was one little thing.

func _process(float):

Your process function isn’t correctly written you need the _ before the process. Also, there is nothing in it, but your _ready function is also missing that.

So I changed the func _process(delta): like you said can’t believe I didnt catch that but for some reason it only spawns the platforms once and doesn’t keep spawning them, do I need PF spawner node somewhere specific?

Weird, for me it kept spawning as I was walking.

I don’t know if there is something else in your code elsewhere blocking it.

Try and create a minimal recreation where you have a parent and just your player and spawner and see if it works. That is what I did since I didn’t have any of your other code, and it kept spawning my object as I walked.

Also, what is that child that you have on PF spawner?

The only other thing I deleted, which shouldn’t I wouldn’t think affect it would be I deleted your pass statements since they aren’t necessary.

Yea even in a basic recreation with player and spawner it’s not working.When I move the PF spawner location I get an Invalid access to property or key 'global_position' on a base object of type 'Vector2'. on this line
spawn_l1.global_position.x = spawn_pos.x
Here’s what I have on my player for movement.

extends CharacterBody2D

var speed = 500
var friction = 250
var gravity = 50
var input = Vector2.ZERO
const max_speed = 600

func _physics_process(delta):
	
	input = get_input()
	position += velocity * delta
	velocity.y += gravity 
	
	
	if input.x == 0.0:
		if velocity.x > (friction * delta):
			velocity = velocity.normalized() * (friction * delta)
			#print("got input")
		else:
			velocity.x = 0.0
	else:
		velocity.x += (input.x * speed * delta)
		velocity = velocity.limit_length(max_speed)
	
	move_and_slide()

func get_input():
	input.x = int(Input.is_action_pressed("right")) - int(Input.is_action_pressed("left"))
	input.y = int(Input.is_action_pressed("jump"))
	return input.normalized()
	

The static body underneath the PF spawner is a base instance for my character to have solid ground.

What is the scene you are trying to instantiate? Because, here it is saying that the object has base type of a Vector2, it is taking issue with your spawn_l1. It is saying it can’t find the global_position because it isn’t of the correct type, but rather it is a Vector2.

I don’t see anything that should impact it in the character movement, and with a minimal recreation it should work. I used your code with the correction of _process(delta) and I put in a placeholder object to spawn in. So, my thought would be your scene you are trying to load has an issue of some type.

It is a scene with a base root of a static body2D, this line is where the instance comes from.
const L1 = preload("res://scenes/platforms1.tscn")

So, I recreated your spawning platforms again, it worked fine for me, this is the code I used

The stucture was parent type Node →
Player
Node2D → holds your code

extends Node2D

const L1 = preload("res://Development 1.3/objects/map_objects/colored_box.tscn")
var spawn_pos = global_position
@onready var player = get_parent().get_node("Player")
const width = 80

func _process(_delta):
	if spawn_pos.distance_to(player.global_position) < 200:
		spawn_platform()

func spawn_platform():
	var spawn_l1 = L1.instantiate()
	add_child(spawn_l1)
	spawn_l1.global_position.x = spawn_pos.x
	spawn_pos.x= spawn_pos.x + width

The only thing I can think would be that your scene you are loading is the problem. Change it to just a sprite scene, and try and load the same thing using only a sprite with an image.


Here’s what I have going on in my scene, I get it to work once without the spawn_l1.global_position.x = spawn_pos.x and same thing if I just use the sprite in the scene. I have a print() to show its spawning and it repeats like it should spawn but only shows up once. And it also only works when I have the PF spawner here in this screenshot.

Okay, what are you trying to accomplish, because I am confused why it is working for me but not you.

When I place the PF spawner on the screen and play the game, once I walk withing 200 pixels it spawns, and then it continues to spawn every 80 pixels as long as I continue walking. Is this what you are trying to accomplish?

yea essentially except with platforms at different heights, like a Mario type side scroller with platforms at randoms places. I figured getting used to doing the procedural generation first with solid ground would be needed. My original idea was to have a couple preset scenes with my placed platforms and then instantiate them randomly as the player moved towards the edge of the screen. Im also confused by this situation im sure its something minor im not seeing so I appreciate all the help you so far! im gonna sleep on it tonight and see if I can spot it with a level head in the morning.

Okay, a couple dumb questions, but I’m baffled why you aren’t able to get it to do what I do.

You have a texture that you can see on your node that you are loading?

You don’t have any weird autoloads or global constants messing with stuff?

You tried to recreate it just with loading a sprite with a texture?

Your character is actually moving towards the point that spawns it?

Im kind of shocked as well but to answer the questions.

  • Yes there is a texture attached to the node.

  • The only other constant I have is in my player script which is for max speed set at 600.

  • Yes I tried with just a sprite and like I said I get the first instance then the rest say they are spawning but I don’t see them

  • I messed around with different placements and just as in last statement yes when I move towards the spawn point and says it spawns and only shows the first one.

Okay, when you test it again, instead of just seeing if they are spawning can you write print(spawnl1.global_position) to see if they are for some reason stacking?

Updated, knew a well rested mind would find it… I feel dumb but I had this line.

spawn_l1.global_position.x = spawn_pos.x

set like this.

spawn_pos.global_position.x = spawn_pos.x

Thank you bearing with my rookie skills!
So if I was gonna do an array of these scenes with groups of random places platforms it would still work?

Ahh that would do it!

Yes as long as you define which scene you want before running what you have it should work.

Example:

Array[scn1,scn2,scn3]

Some func/added code to randomly choose one scn. Then you run the rest with that rand scn stored in var.

1 Like