Can't access node variables from some signals?

Godot Version

4.2.1 (Windows)

Question

Making a very simple game, and using autoloads. I want to send a signal from one class like this:

extends Node

var game: Game

signal changePic(newPic: String)

class MazeCell extends Node:
	var on_enter:Callable
	var maze:Maze
	var down: MazeCell=null
	var up: MazeCell=null
	var left: MazeCell=null
	var right: MazeCell=null

	#not showing up properly???
	func makeMoveDialog():
		var optAry:Array[DialogManager.DialogOpt]=[]
		var newDialog=DialogManager.DialogLine.new()
		newDialog.line=""
		if down!=null:
			var newOpt=DialogManager.DialogOpt.new()
			newOpt.line="South"
                        #IMPORTANT LINE BELOW!
			GameManager.changePic.emit("res://imgs/Gear_3.webp")

And the reciever is here:

class UIDialogManager:
	var label
	var optNodes:Array[Button]
	var textRec
	#var dialogManager:
	
	#what's wrong with calling this signal????
	func setMainPic(res:String):
		print("setMainPic!")
		print(label.visible)

When I try to do anything with the label (such as print out info about it) it gives me a null error, even though the node is both in the scene and initialized.
Additionally, I have another signal that CAN use it, and it looks like this:

func _on_opt_button_0_button_up():
	var curLine:DialogManager.DialogLine=DialogManager.dialog_manager.get_current_line()
	print("Pressed!")
	var curOpt=curLine.opts[0]
	var nextLine=curOpt.on_pressed.call()
	DialogManager.dialog_manager.pop_current_line()
	DialogManager.dialog_manager.add_line(nextLine)
	uiManager.setMainText(nextLine)

	func setMainText(line: DialogManager.DialogLine):
		label.text=line.line

The above works totally fine! Can anyone help me figure out what I’m doing wrong? (All classes here are autoloads).

Sorry to bother you, I’m quite new with gdscript.

You’ve got the wrong idra about signals.

First establish a connection:

# manager - refs to both nodes wants B to talk to A
Node_b.connect("speak", node_a.listen)

# node A - wants to listen to B secrets, has ref to B

Node_b.connect("secret", self.listen)

Func listen(words):
 Print(words)

# node B - something to say
Signal speak(something_to_say:String)
Signal whisper(secret:String)

Speak.emit("hello world")
Secret.emit("password")


My apologies for not specifying. I have a connection here:

func _ready():

       #Connection below
	GameManager.changePic.connect(uiManager.setMainPic)

I know for a fact that connection is established, the issue seems to be that sometimes the receiver function can access local nodes, and that sometimes it can’t.

It CAN access local nodes when I trigger a signal from a button press (on_button_up, as shown above) but not otherwise (when I call changePic.emit()).

I would like to know how to fix this.

Hmm, not sure. All the code provided does not show the signal path being executed.

Where is mazecell created?
who calls mazecell makeMoveDialogue?
How is mazecell.down set?

Thank you for helping me thus far.

Here is the code for makeMoveDialog():

	func makeMoveDialog():
		var optAry:Array[DialogManager.DialogOpt]=[]
		var newDialog=DialogManager.DialogLine.new()
		newDialog.line=""
		if down!=null:
			var newOpt=DialogManager.DialogOpt.new()
			newOpt.line="South"
			#GameManager.changePic.emit("res://imgs/Gear_3.webp")
			DialogManagerUi._on_opt_button_0_button_up().emit()
			#print(GameManager.changePic.get_connections().size())
			#print(GameManager.changePic.get_connections().is_empty())

			newOpt.on_pressed=func():
				maze.getPlayerLoc()
				maze.goSouth()
				#this emits twice???
				#GameManager.changePic.emit("res://imgs/Gear_3.webp")
				return maze.getPlayerLoc().makeMoveDialog()
			optAry.push_front(newOpt)
		if up!=null:
			var newOpt=DialogManager.DialogOpt.new()
			newOpt.line="North"
			newOpt.on_pressed=func():

				maze.goNorth()
				return maze.getPlayerLoc().makeMoveDialog()
			optAry.push_front(newOpt)
		if left!=null:
			var newOpt=DialogManager.DialogOpt.new()
			newOpt.line="West"
			newOpt.on_pressed=func():
				maze.goWest()
				return maze.getPlayerLoc().makeMoveDialog()
			optAry.push_front(newOpt)
		if right!=null:
			var newOpt=DialogManager.DialogOpt.new()
			newOpt.line="East"
			newOpt.on_pressed=func():
				maze.goEast()
				return maze.getPlayerLoc().makeMoveDialog()
			optAry.push_front(newOpt)
		newDialog.opts=optAry

		return newDialog

Here is where mazeCell is created:

class Game:
	var maze: Maze
	func makeMaze():
		var newMaze=Maze.new()

		var cell1 = MazeCell.new()
		cell1.maze=newMaze
		cell1.on_enter=func():print("Entering cell 1!")
		var cell2 = MazeCell.new()
		cell2.maze=newMaze
		cell2.on_enter=func():print("Entering cell 2!")
		cell1.down=cell2
		cell2.up=cell1
		var mazeAry=[[cell1],[cell2]]
		newMaze.mazeAry=mazeAry
		maze=newMaze

And here is where that function is created

func startGame():
	GameManager.game=GameManager.Game.new()
	GameManager.game.makeMaze()
	dialog_manager.dialog_queue.clear()
	var curCell=GameManager.game.maze.getPlayerLoc()
	var newDialog=curCell.makeMoveDialog()
	return newDialog
	#dialog_manager.add_line(newDialog)


func _ready():
	dialog_manager=TextManager.new()
	var dLine1=DialogLine.new()
	dLine1.line="First!"
	dLine1.on_pressed=func():pass
	dialog_manager.dialog_queue.append(dLine1)
	var dOpt11= DialogOpt.new()
	GameManager.game=GameManager.Game.new()
	dOpt11.line="Start Game"
	dOpt11.on_pressed=func():return startGame()

I’m even more lost…

What is dOpt11?

dOpt11 is a dialog option

var dOpt11= DialogOpt.new()
class DialogOpt:
	var line: String
	var on_pressed = func():print("Opt!")

It’s a custom class I made.

The problem is this:

When I call functions from one class (game_manager), it says variables aren’t initialized, but when I call them from another, it says they are. Do you have any idea why this would be?

Dialog

Start game

makeMoveDialog

At the end of all this deOpt11 returns this dialogue to no one…?

Your code is a maze

I don’t even know what the problem is that you are asking. all the signals are commented out and all these lambdas are hard to follow.

An error code would be nice

Let me ask a different, simpler question:

When I type get_node into the editor, sometimes the param will complete with all the nodes in my scene, and sometimes it will only show me the auto loads. Do you know why this would be? And if there’s an easy way to fix this?

It autocompletes with all the nodes when I write it in my parent, but not when I write it in a child node.

There could be lots of reasons…

Does the node even exist yet in the current scene or scene tree?

Sometimes the script compiler is getting hung up on checking correctness in the syntax. You may be in the middle of writing an if statement and you haven’t put the “:” yet. Sometimes it gets confused if you close the parentheses before placing a parameter. Maybe there is a bug in another script that invalidates a whole class everywhere it is used. Godot: “I won’t intellisense until the code is right”.

If I was a Godot dev I would only have get_node recurse down the tree for auto complete, and not back up to parents and cousins and grandparents and distant relatives… etc. since that would be bad practice in general to reference ancestors and cousin. Although they don’t stop you from writing an absolute path or a relative path.

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