Nine agent skills for building Makepad/Rust games, ported from majidmanzarpour/threejs-game-skills. Same director-routed workflow and premium bar; runtime rewritten for this fork's game crates. - makepad-game-director entrypoint, routing, continuity, asset probe - makepad-gameplay-systems loop, movers vs rigid bodies, input, camera, netplay - makepad-aaa-graphics-builder lighting, shaders, budget, visual scorecard - makepad-game-ui-designer HUD, menus, touch and XR UI - makepad-debug-profiler defect bisection and profiling - makepad-qa-release verification ladder, evidence, packaging - makepad-3d-generator CC0 model search, casts, procedural geometry - makepad-image-generator texgen textures, palettes, sky, icons - makepad-audio-generator sample bank, mixer, material impacts, 3D audio Written against the real APIs in libs/game/*, libs/sim and apps/arcade: the game.* verb table, GameRenderer adaptive quality, the packed 6-float GameMeshVertex layout, script_mod! splash styling, makepad-test driving, and the BUDGETS.md numbers. No paid generation API is required - the CC0 library plus seeded makepad-game-gen replaces them. Includes install.sh (Codex/Claude), validate-skills.sh and a repo-aware probe_assets.sh; both scripts verified against this checkout.
87 lines
4.6 KiB
Markdown
87 lines
4.6 KiB
Markdown
# Debug playbook
|
|
|
|
## Rendering
|
|
|
|
| Symptom | Check | Likely cause |
|
|
| --- | --- | --- |
|
|
| Black viewport | camera pos/target, near/far | camera inside geometry; far plane too near; pass not composited |
|
|
| HUD visible, world not | `scene_state` output | camera never updated from sim; rig left at origin |
|
|
| Object missing entirely | `model_is_loaded(id)` | wrong id — **silently degrades to a primitive** |
|
|
| Object at world origin | the `transform` passed to `ModelInstance::new` | identity matrix passed |
|
|
| Object wrong size | `model_bounds(id)` vs player capsule | kit scale mismatch |
|
|
| Z-fighting | coplanar surfaces | offset decals/ground overlays slightly |
|
|
| Object visible through walls | draw order / depth | drawn in the alpha pass when it should be opaque |
|
|
| Flat lighting | `light_dir` on every draw type | set on some, missed on others |
|
|
| Shadows disappeared | `quality_reason()` | adaptive quality cut the shadow budget under load |
|
|
| Props look pasted on | AO | no contact darkening; bake it |
|
|
| Distant geometry on a different backdrop | fog vs sky colour | fog colour does not match the horizon |
|
|
| Sparks look like points on a sphere | firework override | missing per-spark uniform radial angle + swirl |
|
|
| Fine in `cargo check`, broken on launch | — | **the splash DSL resolves at runtime** |
|
|
|
|
## Assets
|
|
|
|
| Symptom | Cause |
|
|
| --- | --- |
|
|
| Everything is primitives | assets never downloaded — run `download_assets.sh` |
|
|
| One thing is a primitive | wrong id; ids look like `kenney/racing/vehicle-truck-yellow` |
|
|
| Tests "pass" but prove nothing | asset-dependent tests **skip** without assets; check for skips |
|
|
| Crowd looks like clones | one cast member reused; vary members, tint, scale, yaw |
|
|
| Animation plays on one character, not another | members from two different casts — pick one cast per scene |
|
|
| Download fails loudly | sha256 mismatch — upstream moved or was tampered with; that is the check working |
|
|
|
|
## Input
|
|
|
|
| Symptom | Cause |
|
|
| --- | --- |
|
|
| Nothing responds | event never reaches the mapping layer; log the action stream |
|
|
| Diagonal movement faster | keyboard vector not normalised |
|
|
| Stick drift / cross-shaped dead spot | per-axis deadzone instead of radial |
|
|
| Jump never fires | ground raycast hits the player's own capsule; filter it |
|
|
| Double jump on one press | input buffer not cleared on use |
|
|
| Works on desktop, dead on phone | touch handled only as mouse; no hover on touch |
|
|
| XR controller does nothing | pose read as gamepad axes; see `apps/arcade/src/xr_input.rs` |
|
|
|
|
## Gameplay
|
|
|
|
| Symptom | Cause |
|
|
| --- | --- |
|
|
| Player floats / snags on seams | player on a rigid body; use a kinematic mover |
|
|
| Crate feels weightless | crate on a mover; use a rigid body |
|
|
| Bullet passes through walls | discrete stepping; use `projectile_ccd` |
|
|
| Character climbs walls | `climb` step height too large; walkable slope unclamped |
|
|
| Lap counts twice | no latch on the checkpoint crossing |
|
|
| Win fires repeatedly | unlatched win condition checked every tick |
|
|
| Second run behaves oddly | `reset()` incomplete — score, timers, emitters, audio voices |
|
|
| Pause does not pause | sim still stepping behind the overlay |
|
|
| Crowd pathing tanks perf | N individual paths to one goal; use a `FlowField` |
|
|
|
|
## Netplay
|
|
|
|
| Symptom | Cause |
|
|
| --- | --- |
|
|
| Clients diverge | variable `dt`; `std` transcendentals; unseeded RNG; `HashMap` order in `step` |
|
|
| Cheating possible | client sending state instead of input — host must be authoritative |
|
|
| Huge bandwidth | replicating vertex data instead of `(preset, seed, position)` |
|
|
| Desync after N ticks | log a per-tick state hash both sides, find the first differing tick |
|
|
|
|
## Script route
|
|
|
|
| Symptom | Cause |
|
|
| --- | --- |
|
|
| Verb rejects an option key | keys are **typo-guarded** — the key is wrong |
|
|
| Handlers stop firing late in a tick | the shared **500k-instruction pool** is exhausted; batch instead of per-entity `on_tick` |
|
|
| Capability denied | `strip_capabilities` / `Trust` — the sandbox working as designed |
|
|
| Verb not found | check `makepad_game_script::api_text()`, the authoritative list |
|
|
|
|
## Bisection recipe
|
|
|
|
When the layer is unclear, binary-search the pipeline rather than reading code:
|
|
|
|
1. Assert the value at the midpoint (instance data handed to the renderer).
|
|
2. Right there? The fault is downstream (draw/shader/pass).
|
|
3. Wrong there? Move up (scene state, then sim).
|
|
4. Repeat. Three or four steps localises almost anything in this engine.
|
|
|
|
## After every fix
|
|
|
|
Add the test that would have caught it, in the lowest layer that can express it — a Cx-free unit test if possible, a `makepad-test` driven test if it genuinely needs the app. A fix without a regression test is a fix with a return date.
|