Concept prototype · Live partner API · Godot 4.6

CharadAI

Charades where you type the clue instead of acting it out. A player types a free-text motion description, and DeepMotion's SayMotion API generates it live on a 3D character in about 20 seconds — everyone else races to guess what it just performed.

Concept prototype — one hypothesis, not a shipped game
Full round captured from the running prototype: type a prompt → live SayMotion generation → reveal on the imported character.
~20sruntime text-to-motion generation latency, per the live SayMotion API
0pre-baked animations — every clip is generated at runtime from a typed prompt
5async API calls orchestrated per round: auth, model lookup, submit, poll, download
2undocumented integration surprises found by reading the SDK source, not the docs
What this prototype tests

A design bet and a technical bet, tested together

Design bet: watching an AI generate a chaotic physical interpretation of a friend's prompt, then racing to guess it, is fun enough on its own to want another round. Technical bet: a .glb file returned by a partner API can be downloaded and played back on a runtime-imported skeleton in Godot 4.6. Full concept in design/gdd/game-concept.md.

Pillar 1

AI is the performer, not you

No player is ever judged on their own acting — the AI takes the credit or the blame, removing the embarrassment barrier Charades normally carries.

Pillar 2

Chaos is content

A weird or wrong AI-generated animation isn't a bug, it's the punchline. Features that make output more "correct" at the cost of funny lose.

Pillar 3

Every reveal is shareable

The generated clip is the entire marketing engine — every UX and technical call defaults toward "this could be posted online in 10 seconds."

Pillar 4

Nobody waits bored

Real generation latency (15-25s) is a fact of the tech, designed around rather than hidden — every wait needs something to react to.

Live API integration

A real partner API, driven end to end at runtime

scripts/saymotion_client.gd is a from-scratch GDScript client for DeepMotion's SayMotion REST API — no SDK for Godot exists, so this reads raw HTTP responses, parses a session cookie by hand, and drives an async job through to a playable animation.

Godot Client SayMotionClient.gd Director types a free-text prompt DeepMotion SayMotion API GET /account/v1/auth → Basic auth, returns dmsess cookie GET /character/v1/listModels → resolve a required model id POST /job/v1/process/text2motion → submit prompt, get back rid GET /job/v1/status/{rid} → poll every 2s, up to 90s GET /job/v1/download/{rid} → resolve the .glb file URL poll loop Live Godot Scene GLTFDocument.append_from_file() Skeleton3D + AnimationPlayer .play() → reveal prompt text .glb download

Two surprises the docs didn't mention

Found by reading the official SDK source and logging raw responses when the quickstart wasn't enough — the kind of debugging a forward-deployed engineer does against any partner's real API.

Symptom · job submit always 500'd

"Model not found" on every job, despite valid auth and a well-formed prompt — the quickstart doesn't mention a required parameter.

Fix

SayMotion requires a model param naming one of the account's own character model IDs. Added _ensure_model_id(), lazily resolved via listModels and cached for the session.

Symptom · polling crashed on the first real job

Code assumed the job id (rid) was numeric and cast it with int() — it crashed the moment a real job came back.

Fix

Logged the raw response: rid is an opaque string like "u5op75geKRgmDXVRfQAB21-text2motion". Never cast it — pass it through as-is.

Symptom · session cookie never attached

Godot's HTTPRequest has no cookie jar — the API's session auth relies on the browser/client remembering a cookie between calls.

Fix

Parses the raw Set-Cookie response header by hand for the dmsess value, then threads it manually into every subsequent request.

Prototype scope, stated up front

Built to answer one question, not to ship

This is a single-scene, single-screen local test — the point is to de-risk the SayMotion integration and the core fun loop before any production build starts. Failure is designed for: every network/API error surfaces its exact message in-UI, and a manual .glb-upload button stays available so a live playtest never hard-stops on an API hiccup.

Deliberately not in this prototype — deferred to the real MVP if the hypothesis holds:
  • No networking or multiplayer — one shared screen, verbal guessing, local test group only
  • No accounts, no persistent scoring across sessions
  • No art polish, no audio, no character skins — 8 hardcoded secret words
  • No server-side credential relay — the API secret is read client-side from a local .env, which is fine for a prototype but must never ship this way in production
Why this matters for forward-deployed engineering

The same loop as a customer integration

Spec before code

The full design (pillars, MDA player-psychology breakdown, MVP cut lines) was written down before any prototype code, so the prototype tested one clear hypothesis instead of drifting.

A real partner API, not a mock

No Godot SDK exists for SayMotion — integrated the raw REST API directly: manual cookie handling, async job polling, and two undocumented requirements found by reading the source.

Fails visibly, ships a fallback

Every API failure surfaces its exact error in-UI, with a manual upload path as a fallback — production-grade resilience thinking applied even to a throwaway prototype.