Issue with player collisions when changing scenes

Hello (sorry for my english).
I have two rooms with two doors (diferent scenes, only one loaded). The door of the first room goes to the second room and the door of the second room goes to the first room. The room doors are both in the same position (0, 1, -6).
The doors are instances of an area3d with the following code:

extends Area3D

@export var exit_to_room_number: int

func _ready() -> void:
	body_entered.connect(_on_body_entered)
	
func _on_body_entered(player: Player) -> void:
	Global.world.change_room(exit_to_room_number)

Global is an autoload with reference to my World node.

Player is a characterBody3D (capsule) that uses the basic movement template provided by Godot.

In the World script I have the following code to switch from one room to another:

extends Node3D

var room_num = 1
var room
var player

func _ready() -> void:
	Global.world = self
	player = get_node("Player")
	room = _load_room(room_num)	
	add_child(room)
	
		
func change_room(go_to_room: int) -> void:
	var new_room = _load_room(go_to_room)
	player.global_position = Vector3.ZERO
	
	remove_child(room)
	add_child(new_room)
	room = new_room


func _load_room(num) -> Node3D:
	var room_id = str("room_", num)		
	var dir = str("res://", room_id, "/", room_id, ".tscn")
	return load(dir).instantiate()

My problem is that when I enter the second room the code for the second door (_on_body_entered) is automatically executed and I return to the first one instead of my player staying at the position (0,0,0) of the second room. I rarely see the second room.

In a more complex code than this one I have tried to create unique collision resources and different scenes for the doors but the problem persists.
In that more complex code I call change_room using call_deferred but it doesn’t work either.
I have loaded the scenes previously and saved them in a dictionary without success.
I have disabled the collision of the player but before I can activate it he goes through the floor of the second room.
I have taken traces and I have seen that the position of the player is updated to (0,0,0) and the player should not collide with the doors but the body_entered of the doors is always called even if the player is at (0,0,0).
I thought the problem was that the physics engine didn’t know that the player had changed position, so I called the change_room method from the player’s own _physics_process, changing its state so that it doesn’t move and activating its movement only after the room has changed. It doesn’t work for me either.
player.force_update_transform() before change position it doesn’t work either.
I have tested with Godot 4.3 and with Godot 4.4 dev 1 and dev 2.
Can anyone give me some pointers on how I can solve this, thanks.

Try this:

extends Area3D

@export var exit_to_room_number: int

var can_switch := false

func _ready() -> void:
	body_entered.connect(_on_body_entered)

func _on_body_entered(player: Player) -> void:
	if can_switch: Global.world.change_room(exit_to_room_number)

func _on_body_exited(player: Player) -> void:
	can_switch = true

To do this, first you need to connect the area body exited signal.

1 Like

Thank you very much for the help and for taking the time to read my problem.
I have not tested the code you have posted because I do not believe that body_entered is executed after body_exited. I think your idea is to simply make the change when the player finish walking out the door, not when the player enter.
I have put what I think you wanted to tell me:

func _on_body_exited(player: Player) -> void:
	Global.world.change_room(exit_to_room_number)

Now it works great! A very simple idea that has never crossed my mind.
Anyway, I’ve done a lot of tests, signals, awaits, etc. and I have not been able to understand why the second door launches the event. Even if you remove the player from the scene, wait a few seconds and add it again the event occurs when there is clearly no collision. I hope that as I understand more how Godot works I will end up understanding why what I had written does not work.
Thank you very much, again.

2 Likes

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