Making a dynamic level swapping system

Godot Version

4.6.1

Question

OK, so I am trying to create a room based level swapping system in godot, and I am encountering some weird behaviour, the main goal is to keep the current room and it's adjacent rooms in the four directions loaded and then keep swapping the neighbours based on the current room. However, for some reason, the neighbour loading only works for the first room, after that, once I exit the starting room it unloads the starting room out of the scene, but doesn’t remove it’s neighbours and no new rooms get added even though my current room does get updated.

class_name LevelContainer2D
extends Node2D

#region Export Variables
@export var player: Player
@export var camera: ZCamera2D
@export var current_level: Level2D
@export var active_rooms: Node2D
#endregion

#region Variables
var rooms: Dictionary[Vector2i, Room2D]
var levels: Dictionary[StringName, Level2D]
var current_room: Room2D
var active_room_ids: Array[Vector2i] = []
var new_room_ids: Array[Vector2i] = []
#endregion


func _ready() -> void:
	for room in current_level.get_children():
		rooms[room.room_id] = room
		room.get_parent().remove_child(room)
	connect_signals()
	on_room_entered(Vector2i(0, 0))


func on_room_entered(_room_id: Vector2i):
	var room = rooms[_room_id]
	if room == current_room:
		return
	id_update(room)
	update_rooms()
	current_room = room
	print(current_room)


func get_neighbours(central_room: Room2D) -> Array[Vector2i]:
	var neighbour_id_list: Array[Vector2i] = []
	for id in central_room.neighbour_ids:
		if id in rooms.keys():
			neighbour_id_list.append(id)
	return neighbour_id_list


func id_update(room: Room2D):
	active_room_ids.clear()
	for child in active_rooms.get_children():
		print(child)
		active_room_ids.append(child.room_id)
	
	new_room_ids.clear()
	new_room_ids.append(room.room_id)
	var new_neighbours: Array[Vector2i] = get_neighbours(room)
	new_room_ids.append_array(new_neighbours)


func update_rooms():
	for id in new_room_ids:
		if id not in active_room_ids:
			active_rooms.add_child(rooms[id])
	for id in active_room_ids:
		if id not in new_room_ids:
			active_rooms.remove_child(rooms[id])


func connect_signals():
	for room_id in rooms:
		rooms[room_id].room_entered.connect(on_room_entered)
1 Like

I think it’s because you are not passing an argument to on_room_entered

You should bind the call:

func connect_signals():
	for room_id in rooms:
		rooms[room_id].room_entered.connect(on_room_entered.bind(room_id))