Variable value found nil when already set (SOLVED)

I can’t come up with an explanation for this error:

function init(self)
	msg.post(".","acquire_input_focus")
	local caretPos = gui.get_position(gui.get_node("Caret")) -- I get the node's position
	print(caretPos)
end

function update(self, dt)
	caret() -- triggers caretActive, turning it on and off
	if caretActive == 1 then
		gui.set_text(gui.get_node("Caret"),"|")
		gui.set_position(gui.get_node("Caret"),caretPos[1]+10*chatLen) -- This is the problem child. It's found nil when I try to set it's X (X, Y, Z) to 10 times the chat length.
	elseif caretPos ~= nil then
		gui.set_text(gui.get_node("Caret"),"")
		gui.set_position(gui.get_node("Caret"),caretPos)
		print("set caret position")
	end
end

My error is that the system seems to be finding caretPos to be nil when I clearly set it in the Init function. I realize using it as a list when it’s a vector is probably not going to return correctly, and I’d need to figure out how to get it’s X position another way, but I was experimenting to see if that would somehow would fix the problem–the system finding it nil.

You are defining caretPos as a variable local to the init function. You need to declare it at the top of your script outside the functions if you want it to exist in the shared scope.

Also your “problem child” line will give you an error once you fix the first issue. When you try to access caretPos[1] it will give an error, “vmath.vector3 only has fields x, y, z.” So you need to use caretPos.x instead. Also if you want to change the x of caretPos you need to do that outside of the gui.set_position function. Instead what your code is trying to do is set the position (vector3) of the node “Caret” to caretPos.x + 10 * chatLen, which is a single number.

3 Likes

An unrelated quick tip: when you’re using a chunk of code like “gui.get_node(“Caret”)” several times in your script, it’s way more convenient, more readable, and might save a tiny bit on performance if you store it in a variable and use that instead. So your code would end up like this:

local caretNode
local caretPos

function init(self)
    caretNode = gui.get_node("Caret")
    -- then you can just use "caretNode" instead of "gui.get_node("Caret")", like so:
    caretPos = gui.get_position(caretNode)
end
2 Likes

Wow, thank you so much for going the extra mile for me! I thought local applied to the script in entirety, but I get it now. It applies to it’s parent, so in this case the Init function. Appreciate it, and the advice :).

1 Like

Yup, it’s just local to the code block that you wrote it in. Take a look at http://www.defold.com/manuals/lua/#_locals_globals_and_lexical_scoping

caretNode and caretPos in your example is not locals for init function. It’s upvalues (external locals).
Also, I think it is best to store reference to node instance in self, like this:

function init(self)
    self.caretNode = gui.get_node("Caret")
    -- then you can just use "self.caretNode" instead of "gui.get_node("Caret")", like so:
    ...
end
2 Likes