ACrucible / Everything Wrong Here Is Silent Intermediate · 6 lessons

Crucible · Intermediate · Tutorial 2 of 3

Six ways to misconfigure a sandbox.
None of them log anything.

The Behavior Sandbox spawns factions of AI agents, has them see each other, fight and complete quest objectives. It reads like a small simulation, and it is — but the interesting part is what it quietly declines to model, and how a typo in a faction name produces a war that never starts rather than an error you could act on.

Application  AshForge Crucible Prerequisites  Warnings Are Allowed Files  *.crucible.json · *.sandbox.json Time  ~35 min

Two different files

A scenario (*.crucible.json) is a repeatable playtest setup: where you spawn, what gravity is, and what static or physics props are in the world. Nothing in it thinks.

A sandbox (*.sandbox.json) is the opposite: no props, just factions, AI agents and an optional quest, on a bare ground plane. This tutorial is mostly about the second.

Why the distinction matters

They clear the world and rebuild it, so you run one or the other. A sandbox will not spawn your scenario's crates, and a scenario will not give you anything that moves on its own.

Both are throwaway. Neither ships. They exist so you can watch something happen and decide whether it looked right.

The theme of this page

Every misconfiguration in the sandbox has a plausible-looking outcome.

Verified: a misspelled relation gives you peace, a misspelled behaviour gives you a motionless agent, a misspelled objective type gives you a ten-second timer, and a misspelled faction id gives you a quest that completes instantly. Nothing warns. If a run looks calm, that is not evidence it is configured.

01

Scenarios

What actually spawns

Do static or physics

A scenario spawn is the placed-object vocabulary you already know — primitive, colour, position, rotation, scale — plus four runtime fields.

FieldDefaultWhat it does
count1Copies, laid out along +X only.
spacing2Gap between those copies.
physicsfalseFalse gives a static body you can stand on; true gives a rigid body you can knock over.
mass1Only meaningful when physics is true.

The static and physics paths build genuinely different things. A static entity gets a trimesh collider — exact, concave, and correct to stand on. A physics entity gets a convex one, because the physics engine will not simulate concave shapes; so a spawned archway you can walk through as scenery becomes a solid lump the moment you set physics: true.

Two smaller things worth knowing. count is clamped to a minimum of one, so "count": 0 spawns one object rather than none. And scale on a physics entity is applied to the mesh and collider rather than the body, which is the correct way to do it but means the two paths respond to scale through different machinery.

Framing
The camera frames a scenario using a fixed 2 m cube per entity, not the entity's real size. A large scaled-up spawn will overflow the frame on load — that is the framing estimate being deliberately cheap, not the spawn being wrong.
02

Factions

Hostility is symmetric

Know no one-way war

Each faction declares relations toward the others — friendly, neutral or hostile. Only one of those words does anything, and it does it in both directions.

You declareYou get
red → blue: hostile. Blue says nothing. Mutual war. Blue is hostile to red too.
red → blue: friendly. blue → red: hostile. War. Hostile wins; friendliness is not protection.
Neither declares anything.Peace. Missing means neutral.
red → red: hostile.Peace. A faction can never fight itself.
red → blue: enemyPeace, silently. Only the exact word hostile counts.
red → ghosts: hostile, no such faction.Accepted without complaint. Ids are never checked.

The symmetry is the one to internalise. There is no such thing as a one-way aggressor here — you cannot set up a predator that hunts a prey faction which ignores it, because declaring the hunt makes the prey hostile back. If you want that asymmetry you get it from behaviour, not from relations: give the prey a low health pool so it crosses the flee threshold on the first hit.

Key
Both silent failures point the same way: toward peace. A typo, an unknown word, a faction you forgot to define — each gives you a sandbox where nothing happens. If your agents are standing around, suspect the relation table first.
03

Perception

A flat cone, and no walls

Know two checks only

An agent sees a hostile if it is within sightRange and inside sightAngleDeg of forward. That is the entire model.

SituationSeen?
Dead ahead, 6 m away, range 12Yes
Directly behindNo — outside the 100° cone
Ahead, 20 m away, range 12No
50 m straight upYes.
Behind a solid wall, 6 m awayYes.

Both surprises come from the same two simplifications. There is no raycast anywhere in the visibility check — geometry between two agents has no effect on whether they see each other. And the whole calculation is flattened onto the ground plane, with height discarded before the distance is measured, so an agent directly overhead sits at a flat distance of zero and counts as seen at any altitude.

Neither is a defect. The sandbox exists to watch faction logic and behaviour states play out on an open plane, and it is built for exactly that. But it does mean the sandbox cannot answer questions about cover, stealth, elevation or blocked sightlines, because it is not modelling any of them — and a run that looks like a stealth test is measuring something else entirely.

Reading the cone
Turn on debug draw to see each agent's cone and live state label. The cone drawn is the real one — same range, same half-angle — so if an agent is not reacting, the picture will tell you whether it is a perception problem or a relations problem.
04

Behaviours

Four names, two behaviours

Do three roads to standing still

The contract documents four behaviours: idle, patrol, guard, wander. Measured over one second of ticks with nobody hostile in the world:

BehaviourMoved in 1s at speed 3
idle0.000 m
guard0.000 m — identical to idle
patrol, no waypoints0.000 m
partol (typo)0.000 m
patrol with a waypoint3.000 m
wandermoves, randomly

guard and idle are the same code path. The two names exist to let you say what you meant, which is worth something in a file someone else will read, but they produce byte-identical behaviour. Do not expect a guard to defend a position more stubbornly than an idler; nothing distinguishes them.

And three of the six rows above give you a motionless agent — but only one of the three is a spelling mistake. The other two are things you asked for. A patrol with an empty waypoint list falls through to the same branch as an unrecognised name, so "my patroller isn't patrolling" has two quite different causes that look the same.

Watch for
Standing still is the sandbox's universal failure mode. It is what you get from a bad behaviour name, an empty patrol route, a mistyped relation, a faction that does not exist, and a correctly configured guard. Debug draw is how you tell them apart — the state label says which branch the agent is actually in.
05

Combat

Combat is arithmetic

Know no dice

Perceive, close the distance, attack once a second until something dies. There is no roll anywhere in it.

BehaviourVerified
Damage per hitExactly attackDamage. No variance, no accuracy, no projectile.
First hit on contactImmediate — the cooldown starts expired.
Subsequent hitsOnce per second.
DeathHealth ≤ 0 removes the agent from the live list at once.
Flee threshold≤ 25% of starting health, boundary included. At 26% it still advances.

Because nothing is random, a fight's outcome is decided before it starts — who wins follows from health, damage and who closed first. That is the point: it makes a sandbox run repeatable, so when you change one number you are looking at the effect of that number rather than at noise.

The flee rule has a detail worth holding on to. Fleeing is a reaction to a visible threat, not a health state: an agent at one percent health with nobody in its cone goes back to patrolling quite happily. It only runs while it can see what it is running from — which also means it stops running the moment the threat leaves its cone, and, since the retreat direction is recomputed every frame as "away from that agent", it runs in a straight line with nothing to stop it leaving the ground plane entirely.

06

Quests

Quests, and four silent typos

Do strictly in order

A quest is a list of objectives that complete one at a time, in order. Two types are supported: elapsed and eliminate_faction.

Sequencing is strict, and it has a consequence people miss: an objective that is already satisfied still waits its turn. If objective three is "eliminate the ghosts" and there are no ghosts, it does not fire early — it fires the instant objectives one and two are done.

The timer restarts at every objective. Two objectives of one second each take two seconds, not one, because seconds is measured from the previous objective's completion rather than from the start of the quest. The data contract's own documentation says "since the quest started"; the code disagrees, and the code is what runs.

What you writeWhat you get
"type": "eliminate_fation" A timer. Unknown types fall through to elapsed, using whatever seconds holds — 10 by default.
"target": "ghosts", no such faction Completes on the first tick. Nobody alive is indistinguishable from nobody at all.
Both mistakes at onceA ten-second wait that looks like a quest.
No objectives at allThe quest never completes, and never says so.
Key
A quest that completes suspiciously fast is nearly always a faction id that does not match. Check it against the factions block by eye — nothing in the tool will do it for you.

Tier two complete

What you now know

Check yourself

  • Scenarios spawn props; sandboxes spawn agents. Each clears the world, so you run one or the other.
  • Static spawns get trimesh colliders, physics spawns get convex ones — the same mesh collides differently.
  • Hostility is symmetric: one declaration makes a mutual war, and hostile beats friendly. There is no one-way aggressor.
  • An unrecognised relation word, and an id for a faction that does not exist, both give you peace, silently.
  • Perception is range plus cone, flattened, with no line-of-sight test. Agents see through walls and see straight up.
  • guard and idle are identical, and a patrol with no waypoints joins them. Standing still is the universal failure mode.
  • Combat has no randomness: exact damage, immediate first hit, 1s cooldown. Flee is ≤25% health and a visible threat.
  • Quest objectives run in order, the timer restarts at each one, unknown types become timers, and a bad faction id completes instantly.

Next, at advanced: running all of this without watching it. Batch runs across every scene in a profile, the report formats, and the performance history that tells you whether last week's change cost you anything.