I’m developing a plugin which generates 100 components and place them on a terrain (with a collider) in the scene.
Issue 1: Scene is not updated
When I execute the plugin function to create components, the scene doesn’t update immediately. To see the changes, I often need to either reopen the project or close Godot entirely. Even then, the update only seems to apply roughly every 5th attempt.
Is there a way to force a scene refresh after the components are generated?
I am using editor_interface.reload_scene_from_path(map_scene.resource_path)
Issue 2: Raycasting the Terrain
I’m having issues with raycasting the terrain. I’m trying to use PhysicsServer3D.space_get_direct_state(terrain_node.get_world_3d())
, but it’s showing an error in the console. What’s the correct way to get the physics space for raycasting in a scene which is not included in the viewport?
My Code
@tool
extends Node
var map_scene = preload("res://scenes/Map.tscn")
var component_scene = preload("res://scenes/Component.tscn")
var editor_interface: EditorInterface
func generate_random_components():
var map_instance = map_scene.instantiate()
# Find the Components node
var components_node = map_instance.get_node_or_null("Components")
if not components_node:
print("Components node not found in the Map scene.")
return
# Remove all existing children from the Components node
for child in components_node.get_children():
print("Removing Component: " + child.name)
components_node.remove_child(child)
child.queue_free()
# Generate Components
for i in range(100):
var component = component_scene.instantiate()
var tag = tag_scene.instantiate()
# Generate random X and Z coordinates
var x = randf_range(-3.5, 3.5)
var y = randf_range(-3.5, 3.5)
var z = randf_range(-3.5, 3.5)
# Raycast to find the Y coordinate on the terrain
var space_state = PhysicsServer3D.space_get_direct_state(terrain_node.get_world_3d())
var ray_start = Vector3(x, 5, z) # Start high above the terrain
var ray_end = Vector3(x, -1, z) # End below the terrain
var query = PhysicsRayQueryParameters3D.create(ray_start, ray_end)
query.collision_mask = 1 # Terrain layer
var intersection = space_state.intersect_ray(query)
if intersection:
y = intersection.position.y
component.position = Vector3(x, y, z)
else:
# Fallback if raycast fails
component.position = Vector3(x, 0, z)
components_node.add_child(component, true)
component.set_owner(map_instance)
# Create a packed scene from our modified map instance
var packed_scene = PackedScene.new()
var result = packed_scene.pack(map_instance)
if result == OK:
# Save the modified scene back to disk
var map_scene_path = map_scene.resource_path
result = ResourceSaver.save(packed_scene, map_scene_path)
print("Saved to: ", packed_scene)
if result == OK:
print("Successfully cleared existing components, added new ones, and saved Map scene at: ", map_scene_path)
else:
print("Failed to save modified Map scene. Error code: ", result)
else:
print("Failed to pack the modified scene. Error code: ", result)
if Engine.is_editor_hint():
print("Reloading scene")
var editor_interface = Engine.get_singleton("EditorInterface")
editor_interface.reload_scene_from_path(map_scene.resource_path)
map_instance.free()