About update() callbacks


#1

Say we have 100…200 (or more) game objects on screen which we should update every frame.
What would be more performant?
a) every object (for example, bullet) will have Defold update callback,
or
b) we have only one “manager” (bullet_system) module with update callback, which updates this many objects (every bullet) in that function. Previously (when created) every bullet registers local update function (not Defold callback) in that bullet_system.


#2

The fewer engine to Lua calls you have the better, so in general A should be more performant than B, but it also depends on what you do in your update function. But with only 100 or 200 game objects it’s doubtful if you actually notice any difference. In my Ludum Dare entry (which I’ve continued to work on from time to time) I let every bullet have it’s own script and update() function and it hardly makes a dent on script performance.

One thing related to this is that when you create a new script or gui_script you’ll get empty/stub lifecycle functions (init, final, update, on_message, on_input). It is a good practice to remove those lifecycle functions that you do not need to minimize the number of engine to Lua calls.


#3

This heavily depends on your logic, but generally Defold is much better at iterating over your content than you can be with Lua.

I did a quick test. 1000 game objects updating their position randomly.

A) Each object updates its position

function update(self, dt)
	local pos = vmath.vector3()
	pos.x = math.random(100)
	go.set_position(pos)
end

On my machine the time fluctuates between 0.7 ms and 1 ms with occasional spikes (garbage collection I would guess)

B) A manager updates all

Manager code.

function init(self)
	self.objs = {}
	for c = 0,1000 do
		local id = factory.create("#factory")
		table.insert(self.objs, id)
	end
end

function update(self, dt)
	for i, id in ipairs(self.objs) do
		local pos = vmath.vector3()
		pos.x = math.random(100)
		go.set_position(pos, id)	
	end
end

Here the time fluctuates between 1.2 ms and 2 ms with occasional spikes. We are generating much more garbage so time varies more.

Note that for B we will probably need to add and remove items from the manager’s object table each frame which will take time.

Still, B might be the way to go if you otherwise need to do a lot of message passing to control the objects. Sending tons of messages each frame is costly, especially on mobile devices.


#4

@sicher, Would you mind trying to not create the vector3 every update and instead create it in init() and reuse it every update()? It would be interesting to see the impact the vmath.vector3() has on the overall script time.


#5

Sure. I get fluctuations around 1.2 - 1.3 ms. Much less gc which stabilizes timing.

I did create the vector3 in the loop on purpose. If you have some more advanced logic for each object it’s pretty hard not to create garbage each loop.


#6

Thanks. I expected the GC to not kick in as often (or at all), but as you say, it’s hard to avoid creating new vector3s in more complex logic.