sorry for weird title... I've got a bit of a strange bug here in my code, and I'm not quite sure what i did wrong.

The situtation: I'm trying to implement a scene change/ doorway system, so that my character can change rooms by being in the correct area and pressing a certain button.

i have 2 variables exported on the door, one that links to what scene the door IS in, and one that links to what scene the door GOES to. Both of these have string values just listing paths- I don't know if this is the best way to do this, but its the one I tried.

Then, inside my scene change (deferred) function, I have get the doors / nodes tagged 'door', and look at them with a for loop to see if they match my old door...

Here's the weird part! the code works ~perfectly~ when I only have one door in a scene, but when I test with 2 doors, it messes up.

I get an error saying that I cannot compare a string and an object with a == operator.

I printed out the different variables to test this, and funnily enough, inside the for loop (and not before it - i printed out the same variable mutliple times through the code) is when it DOES appear as an object. ... this strikes me as really weird. I know I messed up somewhere, I just cannot for the life of me find out where.

Okay thanks for reading all that _ now i'll post the code I'm using:

the script on teh door way:

extends Area2D

#setting as test scene by default, CHANGE LATER
export var scene_door_leads_to = "res://Scenes/TestScene.tscn"
export var scene_we_came_from = "res://Scenes/BigRoom.tscn"
var player
var can_open_door #see if we can open this door! this can come in handy for keys later!
var is_in_door #To see if we are in or out of the door!
#this is so we can have any easy ref to waht door we just came from
#in our global/ autoload scene manager script
signal where_did_we_come_from(where_we_came_from)
signal where_is_player(player)

# Called when the node enters the scene tree for the first time.
func _ready():
	player = null
	self.connect("where_is_player", SceneManager, "return_player")
	self.connect("where_did_we_come_from", SceneManager, "found_our_door")
	can_open_door = false
	print (scene_door_leads_to)
	print (scene_we_came_from)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if Input.is_action_pressed("open_door") and can_open_door:
		move_rooms()


#we may need to move this code to another func
#cuz atm it will only transfer u when u JUST enter and have the righ tkey pressed...


#now the func to actually hold our move room code~!
func move_rooms():
	emit_signal("where_did_we_come_from", scene_we_came_from)
	print (scene_we_came_from)
	SceneManager.goto_scene(scene_door_leads_to)

#when we enter the door we are inside it!
func _on_Doorway_body_entered(body):
	if body.is_in_group("Player"):
		is_in_door = true


#So we can keep the ref to plaeyr outside area 2d func
func find_player(playerskb):
	player = playerskb


#I... dont think I'm using this rn. its just here from an old attempt
func return_player():
	if player != null:
		print ("we foudn player from the doorway script")
		print (player)
	else:
		print ("we did not find plaeyr from doorway script")
	return player


func _on_TimerTilReopenDoor_timeout():
	can_open_door = true

#when we exit the door we can say we are not in the door
func _on_Doorway_body_exited(body):
	if body.is_in_group("Player"):
		is_in_door = false

and the scene manager's script:

extends Node
#memo to self: this script AUTO LOADS! (if i did it right)
#memo to sellf: ANY NODE may connect to or emit signals in an AUTOLOAD script

#NOTE
#When changing scene, we will need this code:
#SceneManager.goto_scene("res://scene_name.tscn")
var current_scene = null
var player_to_spawn = null
var door_we_came_from = null #this is different than current scene in application-\
#we use it to check what the door SAYS we came from.
#current scene is just got when we load the game!!!!
var players_pos = Vector2(0.0, 0.0)

# Called when the node enters the scene tree for the first time.
func _ready():
	var root = get_tree().get_root()
	current_scene = root.get_child(root.get_child_count() - 1)
	#this is assuming the player is always a DIRECT child of the root!!!!


# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass


func goto_scene(path):
	#we MUST defer this or there could be weird behavior!!!!
	#so thats hwy we type the next line
	call_deferred("_deferred_goto_scene", path)

func _deferred_goto_scene(path):
	#before we free the scene we need to find out where we came from!!!
	#take 2 with the code
	#we need to save where we came from
	#and now where we are going to!
	var current_scenes_doors = get_tree().get_nodes_in_group("door")
	var current_door
	var current_scene_name
	for i in range(current_scenes_doors.size()):
		#this line ONLY complains when there is more than one dooor.... :<
		if current_scenes_doors[i].scene_we_came_from != null:
			print (current_scenes_doors[i].scene_we_came_from)
			print (door_we_came_from)
			print (typeof(door_we_came_from))
#			var type_of_door = typeof(door_we_came_from)
#			if type_of_door == 17:
#				print ("we have an object not a string")
			#so atm the first run through on big room we get a string
			#BUT
			#the second run through we get an object???
			if current_scenes_doors[i].scene_we_came_from == door_we_came_from:
				current_door = current_scenes_doors[i]
				door_we_came_from = current_door
				current_scene_name = current_door.scene_we_came_from
	
	if current_door.has_signal("where_is_player"):
		player_to_spawn = current_door.player
		#so we are freing this too so we need a new ref to it!!!!!

	#NOW we can remove the current scene!
	current_scene.free()
	
	#WE ARE JUST COPING PATHS FROM THE FILESYSTEM 
	
	#load the new scene
	var s = ResourceLoader.load(path)
	
	#instance the new scene
	current_scene = s.instance()
	
	#add it to the current scene, as a child of root
	get_tree().get_root().add_child(current_scene)
	
	#this is OPTIONAL but will make it compatible with Scene_Change.change_scene() API
	get_tree().set_current_scene(current_scene)
	
	#now we need a bit of logic to find out what door we are IN and spawn us there
	var doors = get_tree().get_nodes_in_group("door")
	var spawnpoint
	for i in range(doors.size()):
		#we're in a new room now so this door needs to see if the door goes
		#back to whence we came
		#ah. this doens't work b/c one is a scene and one is a string
#		if door_we_came_from != null:
		if doors[i].scene_door_leads_to == current_scene_name:
			spawnpoint = doors[i]
	if spawnpoint != null:
		#player_to_spawn = spawnpoint.player #oh dun this wont work cuz we only find 
		#player when they enter our area2d!!!
		var array_for_player = get_tree().get_nodes_in_group("Player")
		player_to_spawn = array_for_player[0] #Just get the first thing tagged player. there should only be one
		spawn_player(player_to_spawn, spawnpoint, door_we_came_from)

func spawn_player(player, door_to_spawn_from, door_we_came_from):
	var new_player = player #Just testing ...i think this is useless now that I got this test working!
	var new_pos = door_to_spawn_from.position
#	if door_we_came_from != null:
#		#if we are not trying to reenter our current scene
#		if door_to_spawn_from != door_we_came_from:
	new_player.position = new_pos

func found_our_door(door):
	print (door)
	door_we_came_from = door

ack. I deeply apologize, but for the life of me I can never figure out how the code formatting works X_X

@DeanOrTori said: ack. I deeply apologize, but for the life of me I can never figure out how the code formatting works X_X

Hi, you can format the code by selecting all of it, and then click the dropdown on the top of your question textbox that says "Format" when you hover the mouse over it. Then select "Code" and it should work. This will make your question a lot easier to help with.

One other thing, you may already have done this, but it not, make sure you specify which parts of the code are from which scripts and what the scripts are attached too, or we could get confused when trying to help.

Hope this helps. =)

thanks for the format fix, megalomaniak! you're a life saver

Opinionated gamer, I've tried taht before when formatting... it always ends up weirdly formatted for me. I'm not sure what went wrong, I just know it happens every time I put up a question with code X_X

also, just to clarify (for which scripts are attatched to what)

the first script I posted (the one that extends area 2d) is attached to the 'doorway' node (Ie: the node that is in game that can lead to different rooms)

and the second one (extends node) is attached to a 'scene manager'. I just auto load that script however, so IDK if it needs to be attached to anything.

sorry for not clarifying well earlier :3 and thanks you two!

The first thing I would do is to type the variable. var scene_door_path: string = "path".

Megalomaniak, the information is useful, but it would still be nice to split the discussion, thanks :)

and fire7side, thank you, i will try that

ETA 2: im dumb XD its case sensative. thanks I'll try this

Edit: hmm. i tried setting the var as a string like :

export var scene_we_came_from : string = "res://Scenes/BigRoom.tscn"

but it says that It's an invalid export type, and that only built in and native resource types can be exported

the debugger is still saying that the invalid operands string and object in operator ==

even after I typed both scene we came from as string, and door (the passed in value in 'foudn our door')

So I have no idea whats going on :/

String is a class so it's capitalized. I use quite a few languages and get mixed up. String would technically be an object if it's a class. I exported it using String with no errors.

@DeanOrTori said: the debugger is still saying that the invalid operands string and object in operator ==

even after I typed both scene we came from as string, and door (the passed in value in 'foudn our door')

So I have no idea whats going on :/

It's weird, but maybe use a dictionary to get the name, with a number for a key or something. I don't know what else you could do. Maybe use a constant if it's not going to change. It might be some mistake I can't see, but I don't see anything wrong. Good luck. One of them remains a string so you only need to focus on the one that isn't.

hey thanks for the suggestions fire7side.

I've been doing more debugging today and I changed some stuff.

I FEEL there is a problem in my logic but I'm struggling to see it...

I did notice a few basic bugs in a very careful look through my earlier code...

If i get this working I"ll just post the whole new code.

BUt atm i suspect I have a problem in my logic here:

	for i in range(0, current_scenes_doors.size()):
		if current_scenes_doors[i].scene_we_came_from != null:
			if current_scenes_doors[i].scene_we_came_from == door_we_came_from:
				current_door = current_scenes_doors[i]
				current_scene_name = current_door.scene_we_came_from
				print ("We found the correct door")
			else:
				print ("we did not find hte correct door")
				print (current_scenes_doors[i].scene_we_came_from)
				print (door_we_came_from)

I just need to find it X_X

(for those who were curious about the earlier bug, I kinda forgot to call one of the signal functions correctly... :x)

and atm i have that current_scenes_doors[i].scene_we_came_from is not equalling door_we_came_from...

but neither is printing out as null last time i checked.

hence why i suspect its a logic bug i just cant find it.

again thanks all for the patience and help.

I'm gonna take a fiver now and see if i can find it easier later.

If i find it ill let u all know so taht if anyone else has my exact same problem they can see what i did later

okay... for the first part, apparently i set up the signals wrong?

I fixed them now (had forgot to call one function earlier X_X ouch)

anyway. with the help of my brother I got a better way to do the code, and found a BIG bug I'd ignored earlier, or more of, misattributed to another area of code.

Okay _ without further ado, here's the new code, for those who want to know how it looks when it works.

what he told me to do was just directly pass the scene_we_came_from into the goto_scene script, instead of dealing with all the signaling i had earlier. this also enabled me to ditch one of the for loops

doorway code:

extends Area2D

#setting as test scene by default, CHANGE LATER
export var scene_door_leads_to : String = "res://Scenes/TestScene.tscn"
export var scene_we_came_from : String = "res://Scenes/BigRoom.tscn"
var player
#var hold_player #to hold the player between rooms!
var can_open_door #see if we can open this door! this can come in handy for keys later!
var is_in_door #To see if we are in or out of the door!
#this is so we can have any easy ref to waht door we just came from
#in our global/ autoload scene manager script
signal where_is_player(player)

# Called when the node enters the scene tree for the first time.
func _ready():
#	player = null
	self.connect("where_is_player", SceneManager, "found_our_player")
	can_open_door = false

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	#we need to check if we are acutally INSIDE the door oops. forgot that earlier
	if Input.is_action_pressed("open_door") and can_open_door and is_in_door:
		move_rooms()

#now the func to actually hold our move room code~!
func move_rooms():
	print("doorway used, moving scenes " + scene_door_leads_to + " " + scene_we_came_from)
	SceneManager.goto_scene(scene_door_leads_to, scene_we_came_from)

#when we enter the door we are inside it!
func _on_Doorway_body_entered(body):
	if body.is_in_group("Player"):
		is_in_door = true
	find_player(body)


#So we can keep the ref to plaeyr outside area 2d func
func find_player(playerskb):
	player = playerskb


func _on_TimerTilReopenDoor_timeout():
	can_open_door = true

#when we exit the door we can say we are not in the door
func _on_Doorway_body_exited(body):
	if body.is_in_group("Player"):
		is_in_door = false

and scene_manager code (autolaods)

extends Node
#memo to self: this script AUTO LOADS! (if i did it right)
#memo to sellf: ANY NODE may connect to or emit signals in an AUTOLOAD script

#NOTE
#When changing scene, we will need this code:
#SceneManager.goto_scene("res://scene_name.tscn")
var current_scene = null
var player_to_spawn = null
#we use it to check what the door SAYS we came from.
#current scene is just got when we load the game!!!!
var players_pos = Vector2(0.0, 0.0)

# Called when the node enters the scene tree for the first time.
func _ready():
	var root = get_tree().get_root()
	current_scene = root.get_child(root.get_child_count() - 1)
	#this is assuming the player is always a DIRECT child of the root!!!!


# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass


func goto_scene(path, old_path):
	#we MUST defer this or there could be weird behavior!!!!
	#so thats hwy we type the next line
	call_deferred("_deferred_goto_scene", path, old_path)

func _deferred_goto_scene(path, old_path):
	#we can remove the current scene!
	current_scene.free()
	
	#WE ARE JUST COPING PATHS FROM THE FILESYSTEM 
	
	#load the new scene
	var s = ResourceLoader.load(path)
	
	#instance the new scene
	current_scene = s.instance()
	
	#add it to the current scene, as a child of root
	get_tree().get_root().add_child(current_scene)
	
	#this is OPTIONAL but will make it compatible with Scene_Change.change_scene() API
	get_tree().set_current_scene(current_scene)
	
	#this should deal with where we are spawning!
	#now we need a bit of logic to find out what door we are IN and spawn us there
	var new_scenes_doors = get_tree().get_nodes_in_group("door")
	var spawnpoint
	for i in range(0, new_scenes_doors.size()):
		#so this makes all doors 2 directional (enforced)
		#that where we came from is where the door we just entered leads to
		if new_scenes_doors[i].scene_door_leads_to == old_path:
			spawnpoint = new_scenes_doors[i]
	if spawnpoint != null:
		player_to_spawn = find_our_player()
		spawn_player(player_to_spawn, spawnpoint)
	else:
		print ("Spawnpoint NOT set")

func spawn_player(player, door_to_spawn_from):
	var new_player = player #Just testing ...
	var new_pos = door_to_spawn_from.position
	new_player.position = new_pos

func find_our_player():
	var players = get_tree().get_nodes_in_group("Player")
	#this assumes we ONLY have one player
	#which we should but yanno.
	#NEWAY
	var player = players[0]
	return player
	
	

func found_our_player(player):
	print ("our player in 'foudn our player' is")
	print (player)
	player_to_spawn = player

Hope that helps anyone else who makes bugs in similar ways to me :3 thanks for everyone who helped me earlier btw, it was good to start narrowing down all my many problems xD

Glad you got it working. Sometimes you have to rethink it and somewhat start over.

a year later