A variable is being reset after being set, for seemingly no reason

Godot Version

4.3

Question

I’m trying to set up a camera system for my game. The Karl sprite should show when it is set to 1 and the camera is set to 8. But for some reason the camera number keeps getting reset instantly after being set.

here is the code for the cameras

extends Control

var cams = 0 
#^^^the problem veriable in question
var stored_cam = 1

func _ready():
	# Set to invisible by default
	self.visible = false

func _on_computer_pressed():
	cams = stored_cam
	self.visible = true
	print("cams:", cams)

func _on_exit_button_pressed():
	cams = 0
	self.visible = false
	print("cams:", cams)

func _on_cam_1_pressed():
	$cameras.texture = load("res://visuals/Cam1.png")
	cams = 1
	stored_cam = 1
	print("camnum:", cams)

func _on_cam_2_pressed():
	$cameras.texture = load("res://visuals/Cam2.png")
	cams = 2
	stored_cam = 2
	print("camnum:", cams)

func _on_cam_3_pressed():
	$cameras.texture = load("res://visuals/Cam3.png")
	cams = 3
	stored_cam = 3
	print("camnum:", cams)

func _on_cam_4_pressed():
	$cameras.texture = load("res://visuals/Cam4.png")
	cams = 4
	stored_cam = 4
	print("camnum:", cams)

func _on_cam_5_pressed():
	$cameras.texture = load("res://visuals/Cam5.png")
	cams = 5
	stored_cam = 5
	print("camnum:", cams)

func _on_cam_6_pressed():
	$cameras.texture = load("res://visuals/Cam6.png")
	cams = 6
	stored_cam = 6
	print("camnum:", cams)

func _on_cam_7_pressed():
	$cameras.texture = load("res://visuals/Cam7.png")
	cams = 7
	stored_cam = 7
	print("camnum:", cams)

func _on_cam_8_pressed():
	$cameras.texture = load("res://visuals/Cam8.png")
	cams = 8
	stored_cam = 8
	print("camnum:", cams)

func _on_move_timer_timeout():
	print("camnum:", cams)

and here’s the code for Karl

extends Sprite2D

var karl = -1
var karlS = 0
var karlM = 0
var karlP = 0
var karlD = 0

func _ready():
	self.visible = false
	

func _process(_delta):
	# Now check the conditions for karl’s visibility
	if (karl == 1) and (Cameras.cams == 8):
		self.visible = true
	elif (karl == 2):
		self.visible = true
	elif (karl == 3):
		self.visible = true
	else:
		self.visible = false

func _on_move_timer_timeout():
	if karlS == 0:
		karlM = randi_range(1,10) + Movement.kModif
		if karlM > Movement.move:
			karl = karl + 1
			if karl == 6:
				karlP = randi_range(0,1)
				if karlP == 0:
					karl = 7
				elif karlP == 1:
					karl = 9
			if karl == 8 or karl == 10:
				karlS = 2
	elif karlS == 1:
		karl = karl + 1
		if karl == 6:
			karlP = randi_range(0,1)
			if karlP == 0:
				karl = 7
			elif karlP == 1:
				karl = 9
		if karl == 8 or karl == 10:
			karlS = 2
	elif karlS == 2:
		if karl == 8 and Movement.doors[1] == 0:
			karl = 11
			karlS = 3
		elif karl == 8 and Movement.doors[1] == 1:
			if karlD < 2:
				Movement.doors[1] = 0
			else:
				karlD += 1
		if karl == 10 and Movement.doors[0] == 0:
			karl = 11
			karlS = 3
		elif karl == 8 and Movement.doors[1] == 1:
			if karlD < 2:
				Movement.doors[1] = 0
			else:
				karlD += 1
	elif karlS == 3:
		@warning_ignore("standalone_expression")
		Kills.karl_kill

	print("karlM:", karlM)
	print("karlS:", karlS)
	print("karl:", karl)
	print("camnum:", Cameras.cams)

func _on_state_timer_timeout():
	if karlS == 0:
		karlS = randi_range(0,1)

The relevant variables are not being called anywhere else, and I don’t know where it would be set back to 0. Am I just missing something?

Maybe the timer is causing the issue. Let’s investigate by printing the value of karl at the start and end of the timer function, and also between the if statements, so we can see exactly where it resets

func _on_computer_pressed():
cams = stored_cam
self.visible = true
print(“cams:”, cams)

func _on_exit_button_pressed():
cams = 0
self.visible = false
print(“cams:”, cams)

These are the functions that set “cams” to 0, so can you expand on them?

What are you doing when the cam number is being set/reset? What inputs are triggering these events? Is it possible that input/action in accidently also triggering one or both of these fucntions?

I just did that, I even put a print statement in the process function. The reset is practically instant.

It should only be 0 when I’m not looking at it.

func _ready():
	# Set to invisible by default
	self.visible = false

func _process(delta):
	if cams > 0:
		self.visible = true
	else:
		self.visible = false

func _on_computer_pressed():
	cams = stored_cam
	print("cams:", cams)

func _on_exit_button_pressed():
	cams = 0
	print("cams:", cams)

For some reason, the background of the cameras is completely unaffected. This only affects Karl.

If it only affects Karl, then we should look at when Karl is visible.

func _process(_delta):
	# Now check the conditions for karl’s visibility
	if (karl == 1) and (Cameras.cams == 8):
		self.visible = true
	elif (karl == 2):
		self.visible = true
	elif (karl == 3):
		self.visible = true
	else:
		self.visible = false

So karl starts at -1 as declared, and is set to start invisible. So he starts and stay invisible each frame until…

After 2 timer timeouts, karl should == 1, regardless of the outcome of randomness. So if cams==8 during this iteration, he will be visible, otherwise not.
Then, for the next 2 timer timeouts he should be == 2 and ==3 respectively, making him visible regardless of cams.
After the 5th time timeout, he should hit == 4 and will no longer be visible, regardless of cams value.
He should then remain invisible from karl==4 onward, regardless of cams.

Does this sound like correct behavior? Because that is how I’m reading the code.

Yes that’s about correct. 2 corrections:

  1. Karl is a girl (I don’t believe in name genders)
  2. She should be visible up until she reaches 7 or 10, depending on what path she takes.
func _process(_delta):
	# Now check the conditions for karl’s visibility
	if (karl == 1) and (Cameras.cams == 8):
		self.visible = true
	elif (karl == 2):
		self.visible = true
	elif (karl == 3):
		self.visible = true
	else:
		self.visible = false

This checks every frame for visibility and has no conditions for karl== 7 or 10, so they will default to the else and thus she will not be visible for those values.

If that isn’t what is causing the failure of visibility, I’m inclined to think the problem lies elsewhere, though your code was a bit dense to read through with the very similar variable names and deep if/else trees, so I could be mistaken.

The issue is that the camera is just resetting after the cams variable is set, I don’t think this is an issue with the Karl script.

The Karl sprite should show when it is set to 1
When what is set to 1?

the camera is set to 8.
What variable are you talking about here?

camera number keeps getting reset
And what variable are you talking about here?

The relevant variables are not being called anywhere else,
If only we knew what those were.

I don’t know where it would be set back to 0.
Yikes.

Significant problems in this question.
You have not posted run-able code therefore you must be specific in your questions.
In the absence of these variables being spelled out you are expecting people to step through your code and find a possible problem while not even knowing exactly what the problem is.
It isn’t obvious.
So tell us, what variables are giving you an issue, what your print statements are outputing, and any errors that crop up.
And be specific and detailed.
The better the question, the better (and the quicker) the answers.

1 Like

The karl variable

the Cams variable. #camnums is an artifact.

func _on_exit_button_pressed():
cams = 0
self.visible = false
print(“cams:”, cams)

This is a linked signal function for a button/object, yes?

Is it possible you created your other buttons/objects (camera1-8) by duplicating this, thus duplicating the signal, so each time you press one of them, it send the exit_button_pressed signal, setting your cams = 0?

No, but to to be safe I double checked and that’s not it. Do you want the files so you can tinker with it?

Sure, I think it’d make it much easier to understand the problem

ok, so how do I send them?

Putting them on github and posting the link to the project would probably be best.

link
tell me when you download it and I’ll take it down

I’ve been playing around with your code for a bit now and I’m pretty sure you have a referencing issue, though I haven’t been able to find a solution.

When you are referencing Cameras.cams, I believe it is pulling from the globally loaded variable, which is set on startup. But this is different from the variable “cameras” node, which changes the variables within itself dynamically.

What you need to do is pull the variable from the “cameras” node rather than from the Global list, as the Global list will not change when you change the value in the “cameras” node.
I was struggling to find a way to pull the variable due to how your code and Node tree is structured, though I’m very new to Godot myself so I’m not very well versed in passing signals between nodes yet.

You also have other bugs you will need to squash as well. One I found was in your

func _process(_delta):
	# Now check the conditions for karl’s visibility
	if (karl == 1) and (Cameras.cams == 8):
		self.visible = true
	elif (karl == 2):
		self.visible = true
	elif (karl == 3):
		self.visible = true
	else:
		self.visible = false

I tested this by printing visible / not visible on each statement so I could know when karl was supposed to be visible. However, every time one of the if/elif statements would execute, the else statement would also execute. This wasn’t my main priority so I didn’t dig into it much, but I also don’t see an obvious reason why.

1 Like

问题找到了。
res://scenes/Office.tscn场景起作用的节点是CanvasLayer/Control
而不是自动加载的Cameras
因此,将res://Scripts/Karl.gd文件中的Cameras.cams全部换成$"..".cams
就能解决问题

2 Likes

Okay, that worked apparently.

Would you like to be put in the credits?