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.

    I have been instructed to make the change when the player leaves the gate and not when he enters.
    The following solves my problem:

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

    capitanlopez I have a similar system in my 2d game with doors and listening for player entry. The thing is, when positions change, Godot considers it "moving" so even if you move from one door to another instantly, it still hears "entering." Make sense?

    I have three different ways I solve this but you likely only need one.
    1) Put a "buffer" bool that flips when you exit the area and only flips back when you exit, so it doesn't trigger unless that bool for that door is flipped. (Default it to true then flip to false on exit and have your player signal listen for that.)
    2) Grab the area info of where the player is moving and add to the x or y so you're not exactly in the area when you move.
    3) Have an Input event listening for when the player is present then use a button press to move. Therefore, it's not automatic. It's waiting for a press.

      SnapCracklins Hi
      I solved the problem and simplified my code quite a bit by simply changing the body_entered to the body_exited. I think the first option you mentioned is a similar idea.
      Thanks a lot for the help.