I have been trying to create an asteroid spawner for my game in Godot 4.2.
I've already managed to make my code work on the main scene when running the game, however I'd like to have the same script be able to run as a @tool
on my spawner scene, so I can test everything without having to run the game.
In my asteroid scene, the root node contains a script where asteroids shapes are defined inside _ready()
and require the parameters size
, noise_scale
and noise_adjustment
. Here is the relevant piece code:
extends RigidBody3D
var fnl = FastNoiseLite.new()
var mdt = MeshDataTool.new()
var surface_tool := SurfaceTool.new()
@onready var collision_shape_3d = $CollisionShape3D
@onready var mesh_instance_3d = $CollisionShape3D/MeshInstance3D
var size: float = 5
var noise_scale: float = 1
var noise_adjustment: float = 0
func _ready():
surface_tool.create_from(mesh_instance_3d.mesh,0)
mesh_instance_3d.mesh = surface_tool.commit()
...
...
I created a spawner scene, with a single node containing a script where my asteroid scene is instantiated multiple times, and size
, noise_scale
and noise_adjustment
are all set based on parameters given to the spawner.
@tool
extends Node3D
@export var asteroid_scene: PackedScene
@export var num_asteroids: int = 10
@export_range(0, 1500) var spawn_range: float = 500
@export_range(0, 500) var velocity_range: float = 200
@export_range(1, 500) var min_size: float = 5
@export_range(1, 500) var max_size: float = 200
@export_range(0, 10) var noise_scale: float = 1
@export_range(0, 10) var noise_adjustment: float = 0
# Called when the node enters the scene tree for the first time.
func _ready():
if max_size < min_size:
max_size = min_size
if min_size > max_size:
min_size = max_size
for i in range(num_asteroids):
var asteroid = asteroid_scene.instantiate()
var size = randf_range(min_size, max_size)
asteroid.size = size
asteroid.noise_scale = noise_scale
asteroid.noise_adjustment = noise_adjustment
...
...
add_child(asteroid)
When reloading the spawner scene I get the error message res://Scripts/asteroid_spawner.gd:27 - Invalid set index 'size' (on base: 'RigidBody3D (asteroid_shape_generator.gd)') with value of type 'float'.
I've already tested simply running asteroid.size
without assigning a value, but then I get another error: Invalid get index 'size' (on base: 'RigidBody3D (asteroid_shape_generator.gd)')
I've also tried moving the contents of the _ready()
function into another function and then calling this function inside _process
, which also didn't solve my issue.
I expected to simply have the asteroids spawn inside my spawner scene, just like they do in game (DEBUG)
I've found out that since my asteroid spawner script is a @tool
, then my instantiated asteroids script must also be a @tool
. Simply adding this annotation to the header of my script solved the problem