LUA Naming Collision Issue...maybe? (SOLVED)


A question on function naming.

I’m doing the War battle tutorial, running through the extras, and I have a function called move(self, dt) that updates the location of the tanks.

I also have the same function for the rocket, and the same function for the player.

Everything seems to be fine, until I launch the rocket, when the rocket seems to call the tanks move() and I don’t really understand why.

If I rename the rockets move to rocket_move() then it all works perfectly. It feels like some kind of function naming collision, but I don’t really understand why.


My rocket script in player_rocket.script:"direction", vmath.vector3()) 

function init(self)
	self.speed = 300 = 1

function update(self, dt) = - dt
	if < 0 then
		move(self, dt)

function on_message(self, message_id, message, sender)
	if message_id == hash("animation_done") then
	elseif message_id == hash("collision_response") then
		go.delete(message.other_id)"/gui#ui", "add_score", {score = 100})

function explode(self)
	-- Give ourselves some time to complete the animation = 10000
	-- Reset rotation otherwise the explosion will be rotated
	-- Stop moving
	self.speed = 0
	-- Play explosion"#sprite", "play_animation", {id = hash("explosion")})

function move(self, dt)
	local pos = go.get_position() 
	pos = pos + self.direction * self.speed * dt 

My tank script in tank.script:

local defs = require "modules/defines""parent", msg.url())"dead_zone", 5)

function init(self) = nil
	self.speed = 50

function final(self), "tank_dead", { id = go.get_id() })

function update(self, dt)
	if == nil then
		-- move towards the target at some speed
		move(self, dt)
		-- If we're close enough, we've arrived, drop the target


function on_message(self, message_id, message, sender)
	-- Add message-handling code here
	-- Remove this function if not needed

function on_input(self, action_id, action)
	-- Add input-handling code here
	-- Remove this function if not needed

function on_reload(self)
	-- Add reload-handling code here
	-- Remove this function if not needed

function new_target(self)
	print(go.get_id() .. " has no target, finding new target")
	-- If we don't have a target, pick a random location and move towards it
	-- TODO: Find a way to get a random location within the level bounds
	x, y, w, h = tilemap.get_bounds("/map#map")
	local xt = math.random(w * defs.tile_size)
	local yt = math.random(h * defs.tile_size) = vmath.vector3(xt, yt, 1)

function move(self, dt) 
	if == nil then
		print("WTF " .. go.get_id())
		print("we have target")
		local p = go.get_position()
		local dir = vmath.normalize( - p)
		p = p + (dir * self.speed * dt)

function check_arrived(self)
	local sqr_dist = vmath.length_sqr( - go.get_position())
	local sqr_zone = self.dead_zone * self.dead_zone
	if sqr_zone > sqr_dist then
		print(go.get_id() .. " arrived at target") = nil


You need to make them local.

local function move(self, dt)
    -- stuff

If you don’t write local then they will be global functions that any script can call.

Note that once you make them local you have to define them before (above) where you call them, or forward declare them. See: Locals, globals and lexical scoping


If you create a function in one script without prefixing it with local it will be be defined globally (this goes for regular variables as well).

You are overwriting the same global function multiple times from different scripts. (I agree it might be a bit unexpected since the script specific init/update/etc functions are not overwritten.)

Instead you should do something like this:

-- rocket.script
local function move()
    -- do rocket movement

-- rocket.script
local function move()
    -- do player movement

Then you would be able to use the different move functions separately in each script.

edit: Damn, @ross.grams you are fast!


Thank you both. I was suspicious ti was something like that, but I’d read that function naming between lua scripts that wasn’t an issue.

Thank you for clarifying.


Boom! Beat Sven!


That fixed it, thanks folks. Now I know…and knowing is half the battle.


Yeah, I didn’t know this for a long time either. It makes the weirdest bugs.


Hey now, we both beat @britzl, at least I have that!


Man, y’all are so friendly, and don’t mind my dumb questions.


How come though that we don’t write local in front of the common functions, init, update, on_message and so on?


“There are naive questions, tedious questions, ill-phrased questions, questions put after inadequate self-criticism. But every question is a cry to understand the world. There is no such thing as a dumb question” :slight_smile:


Agreed, it is a bit unexpected since any other functions land in global space… I don’t have any better answer than that those are special instance specific functions that the engine will “remember” and call for that specific component/instance.


He is, quite literally, my hero.

Unrelated question, how many atlases is too many atlases, is it poor form to give hte tanks, and say helicopters seperate atlases?


It depends. If you have a lot of images for the tank it might need a separate atlas (like if it’s 4096x4096), but if both are small you can put the images in the same atlas, that have some performance benefits because the renderer can reduce the number of draw calls.