feat(game): ship the Synty characters — bots are no longer the generated one - #42
Merged
Merged
Conversation
…ted one The bots have used the generated character.glb since the beginning because the Synty animation retarget did not work. It works now (650e8a2 solved it and said so), but it was never wired in, so nothing on screen changed. This wires it. The documented next step was to instrument what placeAnimated returns for the licensed container. Done, with NullEngine, and it found no bug there at all: the retargeted container behaves exactly like the generated character — one __root__, the picked root correct, name.split("_").pop() resolving to idle/walk/run, the mesh present beneath it. The multi-root theory in the handoff was about the OLD import_synty.py output. retarget_mocap.py exports a single target_rig root, so the wiring that failed before simply works. Measured on the animated mesh, not the bind pose: 1.72 m tall, 0.57 m across — arms down, not the 2.03 m T-pose that broke both earlier attempts. fighter_insurgent -> Directorate fighter_soldier -> Nightcell The generated character stays as a fallback, so a failed licensed load degrades to a working bot rather than to none. Clips are MoCap Online's rifle set, in-place variants deliberately: the server owns movement, so root motion would fight the simulation. Shell budget 7.84 MB against the 9 MB guard. Two honest gaps, both recorded in PROVENANCE.md rather than glossed: - The pack ships NO licence, EULA or terms file. It appears to be the free sample pack, but "appears to be" is not provenance and CLAUDE.md requires provenance for every public asset. Fine for a dev build, blocks a paid episode. Swapping clips is a --clips argument, not a code change. - No death animation exists in the pack. Opponents.play() already tolerates a missing clip by stopping every group, so a killed bot freezes rather than erroring — imperfect, and the truth until a death clip exists. Verified: both GLBs load in the real game over the network with zero page or console errors; NullEngine confirms mesh, clips and dimensions. NOT verified: a bot visibly on screen — headless SwiftShader runs at ~1 FPS, so no bot walked into frame during capture. 263 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the "people look identical" fix.
The bots have used the generated
character.glbsince the beginning, because the Synty animation retarget did not work. It works now —650e8a2solved it and said so in its own commit message — but it was never wired in, so nothing on screen changed.The documented blocker did not exist
retarget_mocap.py's header said dropping the result intoOpponentsmade bots invisible, and that the next step was to instrument whatplaceAnimatedreturns. I did that withNullEngine, and found no bug inplaceAnimated:__root____root__split("_").pop()The multi-root theory was about the old
import_synty.pyoutput.retarget_mocap.pyexports a singletarget_rigroot, so the wiring that failed before simply works.Measured on the animated mesh rather than the bind pose: 1.72 m tall, 0.57 m across — arms down, not the 2.03 m T-pose that broke both earlier attempts.
Wiring
fighter_insurgent→ Directorate,fighter_soldier→ Nightcell. The generated character stays as a fallback, so a failed licensed load degrades to a working bot rather than to none. Shell budget 7.84 MB against the 9 MB guard.Clips are MoCap Online's rifle set — in-place (
IPC) variants deliberately, since the server owns movement and root motion would fight the simulation.Two honest gaps, recorded not glossed
1. The animation licence is unconfirmed, and it blocks commercial release. The pack contains no licence, EULA or terms file — only format notes. It appears to be MoCap Online's free sample pack, but "appears to be" is not provenance, and CLAUDE.md requires provenance for every public asset. Fine for a dev build; not fine for a paid episode. Swapping the clips is a
--clipsargument, not a code change.2. No death animation exists in the pack.
Opponents.play()already tolerates a missing clip by stopping every group, so a killed bot freezes in place rather than erroring. Imperfect, and the truth until a death clip exists.Verification, including what I could not verify
NullEngine: mesh present, clips resolve, dimensions correctpnpm checkgreenGiven I have twice this session claimed a visual result I had not actually seen, I am flagging that last point rather than implying otherwise.