For developers coming from Unity, one of the biggest mental model changes when moving to Defold is how behavior is organized on a GameObject.
At first glance, Unity and Defold may seem very different. Unity uses multiple MonoBehaviour scripts attached directly to a single GameObject, while Defold usually uses only one .script component attached to a game object.
But functionally, both engines can support the same modular architecture.
In Unity, it is common to structure a player like this:
Player.csPlayerMovement.csPlayerAttack.csEnemyFinder.csHealth.csEach script is usually a MonoBehaviour, attached to the same GameObject.
Example:
public class PlayerMovement : MonoBehaviour { }
public class PlayerAttack : MonoBehaviour { }
public class EnemyFinder : MonoBehaviour { }
Then a main Player.cs script often acts as the coordinator:
public class Player : MonoBehaviour
{
PlayerMovement movement;
PlayerAttack attack;
void Awake()
{
movement = GetComponent<PlayerMovement>();
attack = GetComponent<PlayerAttack>();
}
}
This gives Unity developers:
In Defold, a game object typically has:
player.script)Instead of attaching many behavior scripts, you place logic into Lua modules.
player.script (attached to object)player_movement.luaplayer_attack.luaenemy_finder.luaSo the attached script becomes the host/controller, while modules behave similarly to Unity components.
PlayerMovement.SpeedUp();
PlayerAttack.Attack();
EnemyFinder.Scan();
local Movement = require "modules.player_movement"
local Attack = require "modules.player_attack"
local Finder = require "modules.enemy_finder"
function init(self)
self.movement = Movement.new(self)
self.attack = Attack.new(self)
self.finder = Finder.new(self)
end
function update(self, dt)
self.movement:update(dt)
self.attack:update(dt)
self.finder:update(dt)
end
The difference is mostly how behaviors are mounted, not whether modular architecture exists.
Behavior modules are attached through the editor.
Behavior modules are composed in code.
That means:
| Unity | Defold |
|---|---|
| Multiple MonoBehaviours on GameObject | One script + multiple Lua modules |
GetComponent<T>() | self.attack, self.movement |
| Inspector composition | Code composition |
| Lifecycle per component | Lifecycle routed through main script |
Defold is intentionally lightweight.
Rather than many script instances on one object, Defold encourages:
You always know where updates start: the attached .script.
Even though the syntax changes, the architecture can stay familiar.
Your old Unity structure:
Can remain exactly the same in Defold.
Only the hosting model changes.
Instead of:
Attach five MonoBehaviours
You now:
Attach one script, instantiate five Lua modules
When porting habits from Unity, I sometime use this structure:
player.go
├── sprite
├── collisionobject
└── player.script
scripts/
player.script
modules/
player_movement.lua
player_attack.lua
enemy_finder.lua
health.lua
Then player.script becomes the glue layer, just like your old Player.cs.
Do not think:
Defold only allows one script, so I lose modularity.
Think instead:
Defold separates runtime host scripts from reusable logic modules.
That is a different workflow—but not a weaker one.
For Unity developers, Defold may initially feel restrictive because you cannot stack many MonoBehaviour scripts on one object.
But once understood, Defold offers the same modular design with less hidden magic and more explicit control.
You still build components.
You just build them in Lua, and assemble them through code instead of the Inspector.
Just like component-based architecture is not mandatory in Unity, it is also not mandatory in Defold. This is only one approach among many. We will explore other ways to solve the same problems in upcoming blogs.