Room system doesn't work as expected

Godot Version

4.4.1 stable

Question

so I made a door system and when you enter a door, you switch from room,For that I use door nodes(I can do that thanks to class_name) + I have an export variable called “next_room”.

When I have more than 1 door in 1 room and the doors don’t have the same room/scene packed in next_room, then on door1 everything goes fine. It teleports you to thee selected room, but if you enter door2. It will not teleport you to the other room, but will give you this error: “Cannot call method ‘instantiate’ on a null value.”

class_name Door
extends Area2D

@export var next_room: PackedScene = preload("res://areas/Widow's Cradle/normal rooms/room_1_1.tscn")
@export var player_position: Vector2

var SAVE_PATH: String = "res://areas/rooms.cfg"

var config: ConfigFile = ConfigFile.new()
var current_room: PackedScene

func _on_area_entered(area: Area2D) -> void:
	change_room(self)

func change_room(door: Door) -> void:
	var room_spawner: Node2D = get_parent().get_parent().get_parent()
	var player: CharacterBody2D = get_tree().get_root().get_node("Main/GameContainer/Game/Game/Player")
	var transition: AnimationPlayer = get_parent().get_parent().get_parent().find_child("RoomTransition").find_child("AnimationPlayer")
	var main: Node2D = get_tree().get_root().get_node("Main")
	
	var last_room: Node2D = get_parent().get_parent()
	door.current_room = door.next_room
		
	transition.stop()
	transition.play("transition")
	player.cutscene = true
	player.velocity.x += 20 * player.direction
	main.cutscene = "transition"
	await get_tree().create_timer(0.7).timeout
	
	
->  var room = current_room.instantiate() # The error is here!
	room_spawner.add_child(room)
		
	player.global_position = door.player_position
	player.velocity.x = 0
		
	await get_tree().create_timer(0.5).timeout
	player.cutscene = false
	last_room.queue_free()

and adding “self” won’t help

This means you are calling a method/function by using a node which is not existed or entered in the render tree.

You did not define current_room in your script. that is why you got this error.

I did define it:

and in my script y typed:

current_room = self.next_room

can you share the script where you define it. Because the script you share above does not have any current_room defined.

class_name Door
extends Area2D

@export var next_room: PackedScene = preload("res://areas/Widow's Cradle/normal rooms/room_1_1.tscn")
@export var player_position: Vector2

var SAVE_PATH: String = "res://areas/rooms.cfg"

var config: ConfigFile = ConfigFile.new()
var current_room: PackedScene

func _on_area_entered(area: Area2D) -> void:
	change_room(self)

func change_room(door: Door) -> void:
	var room_spawner: Node2D = get_parent().get_parent().get_parent()
	var player: CharacterBody2D = get_tree().get_root().get_node("Main/GameContainer/Game/Game/Player")
	var transition: AnimationPlayer = get_parent().get_parent().get_parent().find_child("RoomTransition").find_child("AnimationPlayer")
	var main: Node2D = get_tree().get_root().get_node("Main")
	
	var last_room: Node2D = get_parent().get_parent()
door.current_room = door.next_room
transition.stop()
	transition.play("transition")
	player.cutscene = true
	player.velocity.x += 20 * player.direction
	main.cutscene = "transition"
	await get_tree().create_timer(0.7).timeout
	
	
->  var room = current_room.instantiate() # The error is here!
	room_spawner.add_child(room)
		
	player.global_position = door.player_position
	player.velocity.x = 0
		
	await get_tree().create_timer(0.5).timeout
	player.cutscene = false
	last_room.queue_free()

I think i get your error. If you try to declare the chnage_room value which is a PackedScene in the _ready() function. Your error is solved. By doing this it ensures that the change_room has setted it’s value before it instantiate it.

ERROR DESCRIPTION
The error is why you load the door it somehow does not have value in the change_room. And when you try to make instance of change_room an error occured.

I hope this could help you.

I don’t get it. Can you show me an example please :slight_smile:

Like

func _ready():
change_room = paste your value

any value you want to pass in the change room pass it like that

Like if you are doing thing then make sure door.next_room is not empty

Like

if door.next_room :
door.current_room = door.next_room

Like this

a value? to a function? do you mean a parameter? By the way a parameter is this:

func function(parameter) -> void:

_ready () it godot built in function and executes first when first frame of node/scene entered in the scene tree. it does not require and param

func _ready():
change_room = preload(“res://areas/Widow’s Cradle/normal rooms/room_1_1.tscn”)

I hope you like understand it. But if still confused let me know.

I know what _ready() is, I just didn’t knew what you meant with change_room = value.
Do you mean current_room = preload("something")

That wouldn’t fix the issue though, because every door node has it’s next_room atached. in door1 i chose Room_1_1.tscn, on door2 i chose Room_2_1.tscn next_room is an export variable wich lets me change its value in the inspector. then current_room will have the next_room value, then current_room will be instantiated and the room will be replaced by the current_room. but as you saw, because the 2 doors don’t have the same value. the error apears when entering door2

i just trying to say current_room = next_room

assign the next_room value to current_room in _ready() function. Becuase the error you face says change_room do not have any value when you try to instanciate the object. Like this var room = current_room.instantiate()

that didn’t really fix the issue.

class_name Door
extends Area2D

@export var next_room: PackedScene = preload("res://areas/Widow's Cradle/normal rooms/room_1_1.tscn")
@export var player_position: Vector2

var SAVE_PATH: String = "res://areas/rooms.cfg"

var config: ConfigFile = ConfigFile.new()
var current_room: PackedScene

func _ready() -> void:
	current_room = self.next_room

func _on_area_entered(area: Area2D) -> void:
	change_room(self)

func change_room(door: Door) -> void:
	var room_spawner: Node2D = get_parent().get_parent().get_parent()
	var player: CharacterBody2D = get_tree().get_root().get_node("Main/GameContainer/Game/Game/Player")
	var transition: AnimationPlayer = get_parent().get_parent().get_parent().find_child("RoomTransition").find_child("AnimationPlayer")
	var main: Node2D = get_tree().get_root().get_node("Main")
	
	var last_room: Node2D = get_parent().get_parent()
		
	transition.stop()
	transition.play("transition")
	player.cutscene = true
	player.velocity.x += 20 * player.direction
	main.cutscene = "transition"
	await get_tree().create_timer(0.7).timeout
	
	
	var room = current_room.instantiate()
	room_spawner.add_child(room)
		
	player.global_position = door.player_position
	player.velocity.x = 0
		
	await get_tree().create_timer(0.5).timeout
	player.cutscene = false
	last_room.queue_free()

before running this code
print(current_room)

to check does the current room have any value or is null/empty

I only entered 2 doors

<PackedScene#-9223371904130216115>
<PackedScene#-9223371913877779187>
<null>
--- Debugging process stopped ---

It should only give me the first 2 lines, from where does the third come? I only entered 2 doors

I DISCOVERED THE BUG! THERE WAS NOTHING WRONG WITH THE CODE! Room_3_1 had 2 door nodes, i delted them and I was able to go to Room_3_1 without errors, how?

it means the third door does not have any scene setted. Thats your actual problem.
to fix this you have to assign the third scene but if you have none to assign then try following code.

the below code only set the room when it has any value.

if current_room :
var room = current_room.instantiate()
room_spawner.add_child(room)

Does it get solved ?