I’d like to share some insights based on my experience with Lua modules and script components in Defold. There was also an interesting discussion on Twitter about scripts vs single entry point script in Unity.
https://x.com/keenanwoodall/status/1842587722260898282?t=BbNKQAudwbctz952v482FA&s=19
In my experience, you typically only need one script component per collection proxy. Messages should be used to send commands and data to the GUI or other proxy collections. Don’t make logic on messages, it is hard to understand and debug asynchronous logic
The main disadvantage is that you may need to create an editor for your game or use code to describe levels.
This is how looks controller.script in my games.
local N28S = require "libs.n28s"
local INPUT = require "libs.input"
local SM = require "libs.sm.scene_manager"
local CONTEXTS = require "libs.contexts_manager"
local GAME = require "game.game_world"
local DEFS = require "game.balance.defs.defs"
local POINTER = require "libs.pointer_lock"
local HASHES = require "libs.hashes"
local CONSTANTS = require "libs.constants"
local SOUNDS = require "libs.sounds"
---@class ScriptGame
local Script = {}
function Script:init()
CONTEXTS:register(CONTEXTS.NAMES.GAME, self)
INPUT.acquire(self, nil, SM:get_scene_by_name(SM.SCENES.GAME))
self.fixed_updates = 0
if (html_utils) then
-- Player see loading. So we can collect garbage and user can't see it.
collectgarbage("collect")
timer.delay(0, false, function ()
html_utils.hide_bg()
html_utils.focus()
end)
end
GAME:change_location(DEFS.LOCATIONS.BY_ID.JAM_1.id)
SOUNDS:liveupdate_load_game_sound()
end
function Script:fixed_update(dt)
if self.fixed_updates > 4 then --0,1,2,3
return
end
self.fixed_updates = self.fixed_updates + 1
GAME:fixed_update(dt)
end
function Script:update(dt)
self.fixed_updates = 0
self:check_pointer_lock()
GAME:update(dt)
end
function Script:check_pointer_lock()
if CONSTANTS.IS_MOBILE_DEVICE then return end
if SM:is_working() then return end
if GAME.state.editor_visible then
POINTER.unlock_cursor()
end
if SM:get_top()._name == SM.SCENES.GAME then
if html5 and not POINTER.need_locked and not POINTER.locked and not GAME.state.editor_visible then
SM:show(SM.MODALS.SETTINGS)
end
else
POINTER.unlock_cursor()
end
end
function Script:final()
INPUT.release(self)
CONTEXTS:unregister(CONTEXTS.NAMES.GAME)
GAME:final()
end
function Script:on_input(action_id, action)
if (action_id == HASHES.INPUT.ESCAPE and action.pressed) then
if (not SM:is_working() and SM:get_top()._name == SM.SCENES.GAME) then
SM:show(SM.MODALS.SETTINGS)
end
end
end
N28S.register(Script)