Unexpected offset while spawning along Path3D

Godot Version

4.2.1

Question

Hello Godoteers!

I’m working on a prototype where I’m spawning a packedscene of 3 zombies and a roadblock along a path when a vehicle enters a specific area3D. I have code that spawns correctly and adds in random offsets to make the spacing and location seem more natural but for some reason on the long stretches of the oval track the packedscenes are spawning about -5 units off on the z-axis of where the path3D is placed and I’m not sure why or what could be causing this or even how to debug.

In the screenshot below you can see the oval track, the path3D and in the red boxes is where the packed scenes are spawning even if I remove the random offset. The green boxes look good but I assume if the random spot along the north west outer curve it would also be outside the track.


Here is the packedscene parent node to show there is no inherent offset in the scene, at least as far as I can tell.

Here you can see when the scene is played the packedscene spawning not on the path3D but rather -5 z-axis units offset from it, aka not in the middle of the road.

Here’s the func that spawns the packedscene:

func _on_zombie_spawner_area_3d_vehicle_entered_zombie_spawner():
	print("_on_zombie_spawner_area_3d_vehicle_entered_zombie_spawner called")
	
		# Remove existing roadblocks from the world
	for child in get_children():
		if child.has_node("roadblock"):
			child.get_node("roadblock").queue_free()
	
	# Spawn road blocks
	var progress_step = 1.0 / 10.0 # Divide the range of progress ratios into 10 equal parts
	var current_progress = 0.0 # Start at the beginning of the path

	for i in range(10): # Spawn 10 road blocks
		var zombie_road_block = zombie_road_block_scene.instantiate()   
		zombie_road_block.get_node("zombie_a").vehicle = vehicle
		zombie_road_block.get_node("zombie_b").vehicle = vehicle
		zombie_road_block.get_node("zombie_c").vehicle = vehicle
		var road_block_spawn_location = get_node_or_null("ZombieSpawnPath/ZombieSpawnLocation")
		if road_block_spawn_location:
			print("Spawn location found: ", road_block_spawn_location.global_transform.origin)
		else:
			print("Spawn location not found!")
		# Set the vehicle reference for each zombie and connect signals
		for zombie in zombie_road_block.get_children():
			if zombie.is_in_group("Enemies"):
				zombie.vehicle = vehicle
				#zombie.zombie_killed.connect(sfx_zombie_run_over.play)
				#zombie.zombie_killed.connect(hud.hud_increase_zombie_killing_count_method)
		# Assign a progress ratio from one of the 10 equal parts with some randomness
		road_block_spawn_location.progress_ratio = current_progress + randf() * progress_step * 0.5

		# Get the path direction at the current progress ratio
		var path_direction = road_block_spawn_location.global_transform.basis.z

		# Generate random offsets perpendicular to the path direction
		var random_magnitude = randf_range(-0.0001, 0.0001) # Random magnitude for the offset
		var perpendicular_direction = path_direction.cross(Vector3.UP).normalized() # Perpendicular to the path direction
		var offset = perpendicular_direction * random_magnitude # Offset is now correctly perpendicular to the path

		# Apply the offset to the spawn location
		road_block_spawn_location.global_transform.origin += offset

		# Generate a random rotation angle in degrees, excluding 330-30, 60-120, 150-210, and 240-300 degrees
		var random_rotation_degrees
		while true:
			random_rotation_degrees = randi() % 360
			if (random_rotation_degrees >= 30 and random_rotation_degrees < 60) or \
				(random_rotation_degrees >= 120 and random_rotation_degrees < 150) or \
				(random_rotation_degrees >= 210 and random_rotation_degrees < 240) or \
				(random_rotation_degrees >= 300 and random_rotation_degrees < 330):
				break

		# Convert the rotation angle to radians
		var random_rotation = deg_to_rad(random_rotation_degrees)

		# Create a Transform3D with the random rotation
		var transform = Transform3D()
		transform = transform.rotated(Vector3.UP, random_rotation)
		transform.origin = road_block_spawn_location.global_transform.origin

		zombie_road_block.global_transform = transform
		
		zombie_road_block.scale = Vector3(7.5, 7.5, 7.5)
		
		##zombie.connect("deal_melee_damage", %Vehicle_parent, "_on_zombie_deal_melee_damage")  # Connect to the Zombie's signal
		
		add_child(zombie_road_block)
		
		# Move to the next part of the progress range for the next road block
		current_progress += progress_step

In the code, I’m generating random offsets perpendicular to the path direction and applying them to the spawn location to introduce some variation in the placement of the zombie road blocks. However, even without these offset calculations, there seems to be an inherent offset present. I set the randf_range to a value that is very low (-0.0001, 0.0001) to show that the spawn location isn’t going outside the road based off this random offset.

Has anyone encountered a similar problem or have any insights on what might be causing this offset? I’d appreciate any guidance or suggestions on how to debug and resolve this issue.

Thank you in advance for your help!

Hello
First, your system to generate the random number is not a good idea, you can for example put all your values into an array and shuffle it, then add some randomness with a randi_range
In general, avoid using while loop because it can lead to infinte loop
Then, I dont understand why you need a Tranform3D
I think it would be simpler to add the random number to the rotation property or use rotate() and so avoid any problem with position’s offset, or I don’t get the issue

1 Like

Thanks for looking at this and the reply @yosimitso! I’m sorry I didn’t make my issue clear. Let me try again.

In this screenshot you can see the green “zombies” spawn outside of the road, in the middle of the track.


This position is where the green car is the same in the below screenshot as well (lower left in screenshot)

As you can see the zombies are not spawning on the Path3D, but rather about -5 z-axis units offset from it.

I’m not sure what could be causing this and looking for ideas.

I will try the other suggestions you mentioned but I don’t immediately think they would impact the issue I am seeing.

Cheers!

Ok I get it, I think you should make your code simpler to identify the problem and test it line by line with the step to step debugger to see the generated values
some leads

  • no transform3d to avoid to reassigning zombie_road_block.global_transform a second time (property origin contains the position, so it can cause the issue)
  • save your zombie_road_block with the right scale instead of modifying in into the code (and check if you have an offset in this object)
  • create a “visual debugger”, like raycast, colored rectangles to see where your code operates

good luck, it’s always complicated when you work with Vector 3, basis, transform…

1 Like

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