i started working on a new project and i created a scene which i am hoping to instantiate multiple times with one exported float differing between each instantiation. the effect features two planes with shaders giving a parallax hole effect and a rope running between them. i want to be able to alter the distance between these two planes & the length of the rope (a MeshInstance3D using a QuadMesh) in editor per instance, and i managed to get it working in editor in its own scene.
however when multiple instances exist in the same scene, they share some values but not all. the plane with the shader is moved to the correct location for each instantiation, but the length of the rope is shared per instance.
my code is as follows:
@tool
extends Node3D
var rope
var up
func rope_update() -> void:
# set rope length
var rope_mesh = $rope.get_mesh()
rope_mesh.size.y = self.ROPE_LEN
rope_mesh.center_offset.y = self.ROPE_LEN / 2.0
# set upper hole position
self.up = $up
self.up.transform.origin.y = self.position.y + self.ROPE_LEN
return
@export var ROPE_LEN : float = 10.0:
set(new_len):
ROPE_LEN = new_len
rope_update()
func _ready() -> void:
rope_update()
the second issue arises when i try to launch the game, where i get the following errors: rope_cls.gd:9 @ rope_update(): Node not found: "rope" (relative to "Node3D") rope_update: Attempt to call function 'get_mesh' in base 'null instance' on a null instance.
i’m pretty new to Godot and i am having an extremely hard time wrapping my head around the scope & inheritance of nodes.
i tried to attach videos & images showcasing the behaviour but got an error saying my account is too new.
Resources are shared by default and Mesh is a Resource. You’ll need to make them unique before modifying it:
Enable Local to Scene in the Resource. This will make unique the resource when instantiating the scene (if the resource is shared between nodes in the same scene the copies won’t be made unique)
thanks for the reply ! i have done this but cannot test it even in editor as i am getting the error upon instantiating it inside another scene:
Node not found: "rope" (relative to "Node3D"). res://ent/rope_cls.gd:9 - Attempt to call function 'get_mesh' in base 'null instance' on a null instance.
i’m unsure what the correct syntax is for referencing a child node.
also ! if i am to use Resource.duplicate(), how do i actually implement that ?
For the Node not found: "rope" error: $rope is resolved relative to the node that owns the script. If the script is on the scene root (rope_cls), the child must actually be named rope (case-sensitive), and the lookup can fail in @tool while the instance is still loading inside another scene.
Two practical fixes:
Guard the path and duplicate the mesh before mutating it:
func rope_update() -> void:
var rope_mi := get_node_or_null("rope") as MeshInstance3D
if rope_mi == null:
return
var mesh := rope_mi.mesh as QuadMesh
if mesh == null:
return
# Resources are shared — unique copy before changing size
if not mesh.resource_local_to_scene:
mesh = mesh.duplicate() as QuadMesh
mesh.resource_local_to_scene = true
rope_mi.mesh = mesh
mesh.size.y = ROPE_LEN
mesh.center_offset.y = ROPE_LEN / 2.0
up = get_node_or_null("up") as Node3D
if up:
up.transform.origin.y = position.y + ROPE_LEN
Prefer @onready var rope_mi: MeshInstance3D = $rope and only call rope_update() from _ready() / the export setter after is_inside_tree() is true. In @tool mode that guard avoids the null instance spam when you drop the scene into another scene.
Resource.duplicate() means: duplicate the QuadMesh, assign the copy back to MeshInstance3D.mesh, then edit size / center_offset on that copy. Enabling Local to Scene on the QuadMesh in the inspector does the same for packed-scene instances.
thanks for this ! it worked to stop the errors in editor & on game launch but now i cannot see the scene when instantiated either in editor or in game. it works fine when viewing the rope_cls scene itself.