Skip to content
Development
Skill

/defold-core

Build and debug the core of a Defold game in Lua: game.project settings, collections, game objects and components, script lifecycle and self state, go.property, input focus and bindings, URLs and message passing, factories, collection factories and collection proxies, plus

BOOST
From plugin
awesome-gamedev-agent-skills
4k76 skills
Install
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill defold-core --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/defold-core

Context preview

The summary Claude sees to decide when to auto-load this skill.

Build and debug the core of a Defold game in Lua: game.project settings, collections, game objects and components, script lifecycle and self state, go.property, input focus and bindings, URLs and message passing, factories, collection factories and collection proxies, plus

SKILL.md

defold-core.SKILL.md
name: defold-core
description: >
  Build and debug the core of a Defold game in Lua: game.project settings, collections, game
  objects and components, script lifecycle and self state, go.property, input focus and
  bindings, URLs and message passing, factories, collection factories and collection
  proxies, plus building and smoke-running with Bob. Use when a project has game.project or
  .collection, .go, .script, .gui_script or .input_binding files, or the request mentions
  Defold, msg.post, on_message, on_input, acquire_input_focus, factory.create, collection
  proxy, bob.jar, or a Defold build error.

Defold Core

Structure, wire and verify a Defold game: editor resource files, the Lua script lifecycle, addressing and messages, runtime spawning and world loading, and a Bob build-and-run check. Examples target **Defold 1.14.0**; they were built with Bob 1.14.0 and run on the 1.14.0 headless engine. An existing project keeps its Defold version (see [Version](#version)).

When to use

  • Use when adding or fixing game objects, collections, scripts, input, messages, spawning or

level loading in a Defold project (`game.project` in the root, `.collection`, `.go`, `.script`, `.gui_script` files), or when Bob reports a missing resource.

**When *not* to use:** plain Lua or LÖVE projects (`love2d-core`); GUI layout, sprites, tilemaps and physics depth beyond the pointers in the references; engine-agnostic design handled by the related skills below.

Workflow

1. **Inspect first.** Read `game.project` (`[bootstrap] main_collection`, `[input] game_binding`, `[project] dependencies`), the main collection, and the scripts near the request. Follow the project's folder layout, id naming and message names; do not reorganize. Note which Defold/Bob version CI or the team uses. 2. **Edit the right file type.** Game objects (`.go`) hold components; collections (`.collection`) place game objects and other collections; logic goes in `.script` (game objects), `.gui_script` (GUI) or shared `.lua` modules. Editor files are protobuf text: keep their structure, and copy shapes from `references/file-formats.md` instead of guessing fields. 3. **Check references.** Run `python scripts/check_defold_project.py <project-dir>` (path relative to this skill folder; Python 3.10+, no Defold install needed). Fix every `ERROR` (missing or wrong-case `/paths`, a `game.project` path without the compiled `c` suffix, a `require` whose file does not exist). Warnings cover files nothing uses yet, unfetched library dependencies and runtime-loaded files. Re-run until it exits 0. 4. **Build with Bob.** `java -jar bob.jar --root . --variant headless --archive resolve build` needs JDK 25 and a `bob.jar` matching the project's Defold version. Exit 1 plus an `ERROR:` line means a broken reference or a Lua syntax error (with file and line); `references/file-formats.md` shows how to trace an error that names a generated file. 5. **Run it.** A build does not prove the game works. Run a headless bundle under a timeout (`references/build-and-run.md`) and read the log: `ERROR:SCRIPT:` lines are Lua runtime errors, `ERROR:GAMEOBJECT:` lines bad addresses or socket clashes. Require a line your test prints when it finishes; the exit code alone proves nothing. The headless engine has no keyboard or mouse, so check input changes in the editor or a desktop build, and say what you could not verify.

Patterns

Project and resource references

`game.project` is an INI file in the project root. Resource paths everywhere are root-absolute (`/main/player.go`). In `game.project` they name the **compiled** file, so the source path gets a trailing `c`:

[bootstrap]
main_collection = /main/main.collectionc

[input]
game_binding = /input/game.input_bindingc

Bob builds only what is reachable from `game.project`; `/builtins/...` ships with the engine.

Collections, game objects, components

A collection places instances and can override script properties per instance; a game object lists file components and embedded components (escaped `data:` strings). Full verified files are in `references/file-formats.md`.

# main.collection (excerpt): place player.go and override its script's speed
instances {
  id: "player"
  prototype: "/main/player.go"
  component_properties {
    id: "player"
    properties { id: "speed" value: "250.0" type: PROPERTY_TYPE_NUMBER }
  }
}

Script lifecycle, `self` and properties

go.property("speed", 200)                   -- top level only, literal default; editable per instance

local LEFT = hash("left")                   -- hash ids once, not every frame
local RIGHT = hash("right")
local FIRE = hash("fire")

function init(self)
	msg.post(".", "acquire_input_focus")    -- no focus, no on_input calls
	self.held = {}                          -- per-instance state lives on self
end

function update(self, dt)
	local dir = (self.held[RIGHT] and 1 or 0) - (self.held[LEFT] and 1 or 0)
	if dir ~= 0 then
		local pos = go.get_position()
		pos.x = pos.x + dir * self.speed * dt    -- dt-scaled: same speed at any frame rate
		go.set_position(pos)
	end
end

function on_input(self, action_id, action)
	if action_id == LEFT or action_id == RIGHT then
		if action.pressed then self.held[action_id] = true
		elseif action.released then self.held[action_id] = nil end
		return true                         -- consumed: listeners lower on the stack skip it
	elseif action_id == FIRE and action.pressed then
		factory.create("#bulletfactory", go.get_position(), nil,
			{ velocity = vmath.vector3(0, 600, 0) })
		return true
	end
end

function final(self)
	msg.post(".", "release_input_focus")
end

Callbacks: `init`, `final`, `fixed_update`, `update`, `late_update` (after every `update`, before render), `on_message`, `on_input`, `on_reload`. Update order between game objects is unspecified. `fixed_update` runs 0..N times per frame at `[engi

Read more
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Get the whole plugin