Replacing one instantiated scene with another

Godot 4.x

I want to have my character replace an apple with an orange. Simple, I thought. I don’t want to just change the mesh but all of it. Brand new node where the old one was with a new model and collision shape.

I already have a system to detect an interactable object, prompt me and delete the first object when I press [e] but putting the new, changed one in it’s place is where I hit a wall.

So, I have seen a lot of conflicting solutions to this problem and none of them seem like good options for my situation. I have to be missing something obvious because this seems like an easy functionality but alas, I cannot find anyone talking about it :confused:

Any help is appreciated!

What do you want to happen? As you’ve stated this could have many different solutions depending on what exactly you want to happen. What are the goals of your pick up/put down system?

Do you have any code written down?

I want the original gone and new node exactly in the same place. No pick up or move. Just turning one thing into another

You can do something like that as an example. This instantiates the new scene as a new node, puts it in the same place in the scene tree as the old node, copies the transform of the old node and then finally removes the old node.

@export var new_node_scene: PackedScene

func change_scene() -> void:
    var new_node = new_node_scene.instantiate()
    old_node.add_sibling(new_node)
    new_node.transform = old_node.transform
    old_node.queue_free()
2 Likes

I will try that! Thank you!!

Okay so, Cheers! It worked to turn an apple into an orange!! THANK YOU!

Slight problem, I can now not reference that scene in reverse to turn the orange back into an apple, or anything into an apple for that matter…

Errors
error "cannot call method ‘instantiate’ on a null value.
E 0:00:00:682 _printerr: res://Foods/Scenes/Orange-Whole.tscn:57 - Parse Error: [ext_resource] referenced non-existent resource at: res://Foods/Scenes/Pomme-Whole.tscn.
<C++ Source> scene/resources/resource_format_text.cpp:39 @ _printerr()

It looks like queue.free() never lets it replace ANYTHING with an apple with this code… Technically my game doesn’t need this functionality for what I have currently planned but I can see this being problematic down the line so I was wondering if you knew another way to remove the previous scene WITHOUT that problem.

remove_child(current_fruit) failed with the same errors…

extends Interactable
class_name Fruits

@onready var current_fruit: RigidBody3D = $"."

@export var chopped_scene: PackedScene

func _on_primary_interact(body: Variant) -> void:
	print(body.name, " chopped ", name)
	var new_fruit = chopped_scene.instantiate()-
	current_fruit.add_sibling(new_fruit)
	new_fruit.transform = current_fruit.transform
	current_fruit.queue_free()

remove_child(current_fruit) failed with the same errors…

This error says that your scene is a null at the time you’re trying to call instantiate() on it. Just make sure its not null.

1 Like

If your scenes reference each other through the exported PackedScene ie. Apple ⇆ Orange this is a cyclical reference Godot cannot resolve and instead drops the reference. You can use a string path instead, so you only require a String rather than a whole scene.

@export_file("*.tscn") var chopped_path: String

func _on_primary_interact(body: Variant) -> void:
	print(body.name, " chopped ", name)

	var chopped_scene: PackedScene = load(chopped_path)
	var new_fruit = chopped_scene.instantiate()

	self.add_sibling(new_fruit)
	new_fruit.transform = self.transform
	self.queue_free()
2 Likes

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