What are the options to divide update?

I’m interested if there’s any native option to divide update function in like 3 sections. I mean like it’s done in Gamemaker step begin/ step/ step_end - if any instance has to code in step_begins, then step is happening when all instances have completed step_begin. Same goes for step_end - it happens after every instance has done step code.
For my limited knowledge, I can think only using like manager object that loops through all instances and launches step_begin/ step/ step_end for them. And I’m not really sure yet how to pull that off.
Basic need where I’d want to use it is to position the camera in step_end after all instances have moved their positions and then position camera.

One way is with a very simple lua module to manage subscriptions, like so:


local M = {}

local sub = {}

function M.subscribe(message, self, callback)
	sub[message] = sub[message] or {}
	sub[message][self] = callback
end

function M.unsubscribe(message, self)
	if sub[message] then
		sub[message][self] = nil
	end
end

function M.call(message, ...)
	if sub[message] then
		for self,callback in pairs(sub[message]) do
			callback(self, ...)
		end
	end
end

return M

Any objects that you want to get the callback will need to subscribe on init and unsubscribe on final.

local callbackManager = require "main.callback_manager"

local function pre_update(self, dt)
end

function init(self)
	callbackManager.subscribe("pre_update", self, pre_update)
end

function final(self)
	callbackManager.unsubscribe("pre_update", self)
end

Then you need one script to actually trigger the callbacks. And all the subscribers will get it.

function update(self, dt)
	callbackManager.call("pre_update", dt)
end

Yeah, Defold really needs a late update for camera stuff (after physics updates, etc.). The render script update would work, but it doesn’t have access to any “go.” functions, so you can’t really do anything with it. The “usual” method is for the camera to send a message to itself every update. That message response will be a sort of post-update—guaranteed to happen after all update() functions have finished—but it’s still before physics updates if I recall correctly.

2 Likes

Wow, thank you! I’ll try it out.
Does it means only one instance should call - callbackManager.call(“pre_update”, dt), for all subscribers to execute function?

Yes.

1 Like

I was just experimenting with something like this for my own project, and reminded myself of the big drawback with this: The functions will be called from a different context.

With your pre-update example, all the objects’ pre-update functions will be called within the context of the script that called “callbackManager.call()”. This means that relative URLs and anything else that is assumed to be working on the current object will work on the original function caller, certain namespaces may not be available (such as gui. if a game object sent the “call”), timers get weird, and probably some other limitations.

This may not be a deal-breaker in some cases, but definitely makes life more difficult.

1 Like