BuildBattle Docs
Unity 6 · URP · Robot Combat Kit

Build a robot. Arm it. Send it to war.

BuildBattle is a modular, physics-driven robot construction & combat sandbox for Unity — a spiritual successor to Robot Arena 2. Design a chassis from scratch, pack it with parts inside-out, paint it, validate it, then drive and fight it in a physics test garage. This handbook teaches you everything: playing, building, customizing, and extending the kit with your own content.

The BuildBattle combat arena with two robots and a live HUD

New here? Read this top to bottom — each section builds on the last. Already comfortable? Jump straight to the Component Catalog, Developer Tools, or Extending the Kit.

Overview

Everything in BuildBattle is built from simple primitives — the depth lives in the mechanics, not the meshes. Two ideas explain the whole kit.

🧩

Code-first & data-driven

One master registry of part types (PartCatalog) is the single source of truth. The build palette, placement rules, physics, save files, and baked prefabs are all derived from it. Add one part and it flows through the whole kit.

⚙️

Real physics, real damage

Bots are rigidbodies wired with hinges and welds. Weapons deal a two-axis (piercing / concussion) blow, armour hardness resists it, and every wheel and weapon takes localized damage — wheels pop off, spinners go unbalanced.

🔁

Procedural, but bakeable

Parts, chassis, arena, sounds and FX are generated from code, then a one-click Bake Asset Library projects them into normal Unity assets (prefabs, materials, meshes, .wavs) you can drag around.

🛠️

Built to extend

Adding a component, weapon, material, paint colour, sticker, sound, FX, or a whole new bot is a small, well-documented catalog edit — and unit tests guarantee anything you ship can be hand-built by a player.

How the pieces fit together

A robot is a BotDefinition: a procedurally-built chassis plus a list of parts, each snapped to the floor or onto another part's socket. You assemble it in the Workshop, then spawn it in the Garage where BotSpawner turns each part into a live rigidbody, hinge joint, or weld.

The sandbox aesthetic is intentional. Boxes, cylinders, discs and bars keep the focus on engineering and physics. When you extend the kit you compose the same primitives — there are no art pipelines to fight.

Install & Requirements

BuildBattle is a Unity package folder. Drop it into a URP project with the new Input System enabled and you're ready.

DependencyVersion / Notes
Unity6000.4.0f1 (Unity 6) or newer
Render PipelineUniversal Render Pipeline (URP) — must be the active pipeline
Input Systemcom.unity.inputsystem (new Input System backend)
Test Frameworkcom.unity.test-framework (for the included EditMode tests)

The project ships URP render-pipeline assets in Assets/Settings/ and an input map at Assets/InputSystem_Actions.inputactions. If you drop BuildBattle into an existing project, make sure URP is active and the new Input System backend is enabled (Edit ▸ Project Settings ▸ Player ▸ Active Input Handling).

First thing to open: the menu Tools ▸ BuildBattle ▸ Hub. It auto-opens once per session and is the one-stop panel to open scenes, bake the asset library, capture screenshots, and open the docs. See Developer Tools.

Quick Start

From a fresh import to driving your first robot in about a minute.

  1. Open the Hub

    Menu: Tools ▸ BuildBattle ▸ Hub. From here you can open any scene, bake assets, capture media, and reach this documentation. (It also opens automatically once per session.)

  2. See it instantly

    Open Assets/BuildBattle/Demo/Showcase.unity — a lit arena with the pre-made bots laid out and framed by a camera. (Generated by the Asset Library baker.)

  3. Play the Workshop

    Open Assets/BuildBattle/Scenes/Workshop.unity and press Play. The step-by-step wizard walks you through footprint → height → armour → components → paint, or start from a complete pre-made bot. Validate, then hit Test to enter the garage. Full walkthrough in The Workshop Wizard.

  4. Fight in the Garage

    Drive, spin up your weapon, and press F to spawn an opponent — or P to sit back and watch an AI-vs-AI brawl. Controls below.

Garage controls

WASD Drive Space Spin up weapon Q/E Weapon slower / faster Tab Drive mode (Arcade / Tank) R Respawn F Spawn / remove opponent P Autopilot (watch AI vs AI) C Cycle camera (scroll = zoom)

Why scenes show a "preview" you can't edit at runtime: BuildBattle builds its real, playable world procedurally on Play (camera, lights, arena, UI, bots). Each scene also carries an editor-only EditorScenePreview so it isn't empty when you open it; BuildBattleApp removes that preview the instant the procedural build starts.

The Workshop Wizard

The Workshop is a guided build wizard. It takes you from a bare footprint to a battle-ready, validated robot — and every step enforces the same rules the physics simulation uses, so a bot that builds is a bot that fights.

The build flow

Open Scenes/Workshop.unity and press Play. You can either start a fresh chassis or pick a pre-made bot and modify it. The wizard advances through these steps:

  1. Base Shape — draw the footprint

    Sketch the chassis floor on a 0.05 m grid. This is the bot's footprint; everything else rests on or inside it. The mass budget for your weight class is shown live.

  2. Height — extrude the shell

    Pull the footprint up into a 3-D shell. Taller shells weigh more (armour volume) but enclose more internals.

  3. Armour — pick a material

    Choose Plastic, Aluminum, Titanium, or Steel. Each trades density (weight) against a health multiplier and a hardness that resists piercing damage. See Weapons & Damage.

  4. Components — pack it inside-out

    Place a control board, battery, drive motors + wheels, and any weapon. The shell turns see-through so you can position internals precisely. Parts snap to the grid or glow-snap onto compatible sockets. Live panels show mass, power, top speed, weapon damage, and a pass/fail validation.

    The bot is seated on the floor under live physics as you build: add a wheel and the whole machine smoothly rises to ride on it, so nothing ever clips through the baseplate, and loading a pre-made bot drops it onto its wheels instantly. What you see resting in the workshop is the stance it fights with.

  5. Paint Shop — finish & mask

    Wash the armour with a colour, stick on livery, and place functional hole/slot masks where weapon shafts pass through the shell. See the Paint Shop section.

  6. Validate & Test

    The validator confirms the bot is legal (has a brain, a battery, 2+ driven wheels, fits its weight class, has enough power). Then Test drops you into the garage.

Built inside-out: the build progression

Because you build from the floor up, a finished bot is really layers of legal placements. Here's the same chassis growing from bare shell to complete machine:

Fastest way to learn: start from a pre-made bot (e.g. Bar Spinner), step backward through the wizard, and watch how each layer was placed. Every preset is hand-buildable with exactly these tools — that's a guarantee enforced by tests (see Testing).

Inside the Bot

BuildBattle is an inside-out builder: the interesting engineering is the guts. During the Components step (and in these cutaways) the armour shell goes translucent so you can see exactly how the drivetrain and electronics are arranged.

The anatomy of every robot

  • Chassis — the procedurally-extruded armour shell. Its material sets weight, durability, and hardness.
  • Control board — the brain. Exactly one per bot, and it's protected from being knocked off so a bot can't be trivially disabled.
  • Battery — provides capacity (Wh), pack voltage, and peak output (W). Voltage and wattage are both checked against the motors (see Power Budget).
  • Drive motors + wheels — each motor exposes an axle socket; one wheel snaps per axle. Motors at the corners give a wide, planted stance.
  • Weapon system — one of three families: a static weapon welded to the floor (wedge, spike, cleaver); a spinner chain (weapon motor → extender → implement); or an actuated weapon hinged to the chassis and fired on command (flipper, hammer, overhead axe).

Because internals sit behind armour, electrical parts (battery, motors, brain) also smoke as the bot's overall health drains — a dying machine visibly cooks from the inside. Pass-throughs (a spinner shaft poking out) can be tidied with hole/slot mask stickers.

Component Catalog

Every buildable part, straight from PartCatalog. Each part has a category (its behavioural class), a dry mass, hit points (before the armour multiplier), and category-specific stats. The palette shows these live as you build.

Part categories

ControlBoard Battery DriveMotor Wheel WeaponMotor Weapon Extender Structural

Brain & power

PartidMassHPKey stats
Control Boardboard_basic0.4 kg25draws 5 W · one per bot · undetachable
NiMH Pack (S)battery_small1.6 kg3060 Wh · 12 V · 1500 W out
LiPo Pack (L)battery_large3.2 kg45160 Wh · 24 V · 7000 W out
Cell Barrelbattery_barrel2.2 kg35110 Wh · 18 V · 3500 W · cylindrical

Drive

PartidMassHPKey stats
Speed Motormotor_speed1.8 kg401.2 Nm · 4200 rpm · 350 W · 12–24 V (overvolt)
Torque Motormotor_torque2.6 kg554.5 Nm · 1600 rpm · 480 W · 12–24 V
Wheel (S)wheel_small0.8 kg22r 0.09 m · w 0.06 m · grip 1.4
Wheel (L)wheel_large2.0 kg34r 0.13 m · w 0.09 m · grip 1.5

Weapon motors

PartidMassHPKey stats
Spinner Motor (horiz)wmotor_spinner3.5 kg6012 Nm · 5000 rpm · 900 W · 24–36 V · spins flat (Tombstone)
Vertical Spinner Motorwmotor_vertical3.6 kg6012 Nm · 4600 rpm · 900 W · upright undercutter (Minotaur)

Weapon implements

PartidMassHPBite (P/C)Mount
Spinner Barweapon_bar2.4 kg700.60 / 0.25weapon mount
Beater Bar (30cm)weapon_bar_short1.8 kg580.70 / 0.30weapon mount
Heavy Bar (70cm)weapon_bar_long3.8 kg950.70 / 0.35weapon mount
Spinner Discweapon_disc2.8 kg850.85 / 0.15weapon mount
Flywheel Disc (40cm)weapon_disc_heavy4.6 kg1200.80 / 0.30weapon mount
Front Wedgeweapon_wedge2.0 kg60Wedge (dir.)chassis floor
Spike Prongweapon_spike1.2 kg45Spike (dir.)chassis floor
Cleaver Bladeweapon_axe3.0 kg90Axe (dir.)chassis floor

P/C = piercing / concussion shares. “dir.” weapons only bite along their working face — see Weapons & Damage.

Actuated frame weapons

These bolt to the chassis floor but, unlike a fixed wedge or spike, they're hinged and driven: they park at a rest pose and swing on command (Space, or the AI when a foe is lined up). See Actuated weapons.

PartidMassHPActionMount
Flipper Plateweapon_flipper2.2 kg70flings a foe up & over (launch impulse)chassis floor
Hammer Armweapon_hammer3.6 kg95rears up tall, slams its head forward/downchassis floor
Overhead Axeweapon_axe_pole3.2 kg90stands over the deck, chops down on the foechassis floor

Reach & ballast

PartidMassHPKey stats
Extender (10cm)extender_short1.0 kg55relays a weapon mount 0.10 m outward
Extender (20cm)extender_long1.7 kg65relays a weapon mount 0.20 m outward
Ballastballast_block4.0 kg50inert mass — tune balance & weight class

Sockets — how parts connect

Parts seat using one shared snap function (SocketSnap), so a placement in the workshop lands byte-for-byte where a pre-made bot's data put it. Three socket types matter:

  • ChassisFloor — a part rests on the baseplate (grid-snapped). Most internals and static weapons.
  • MotorAxle — a drive motor exposes axle_l/axle_r; one wheel snaps per axle.
  • WeaponMount — a weapon motor exposes a mount along its spin axis; an extender or implement snaps on. Extenders re-expose a fresh tip mount further out.

Weapons & the Damage Model

How hard a blow lands is a two-axis model lifted from Robot Arena 2, all living in CombatMath. Understanding it is the key to designing both weapons and armour.

Piercing vs concussion

Every weapon's bite splits into two shares (a WeaponDamageProfile):

  • Piercing — sharp, armour-defeating force (discs, blades, spikes). Blunted by hard armour.
  • Concussion — blunt force that punches through plate regardless (hammers, rammers, wedges).

The pair feeds the RA2 damage potential, surfaced as dmg N in the part picker:

D = 183.9 · piercing + 100 · concussion

Armour hardness resists piercing — not concussion

Each material carries a hardness on the RA2 scale. Harder shells shrug off the piercing share of a hit while concussion sails straight through. So a sharp spinner wants a soft target, and a blunt hammer doesn't care what you're made of.

MaterialDensityHP ×HardnessTakes ~ of a sharp hit
Plastic1200 kg/m³0.5×80~125%
Aluminum2700 kg/m³1.0×100~100%
Titanium4500 kg/m³1.6×150~68%
Steel7850 kg/m³2.0×175~57%

Directional weapons only bite along their face

A profile may set UsesDamageNormals with a local working direction and a tolerance cone. A front wedge bites forward/up, a fixed spike straight ahead, and a nose cleaver chops forward-and-down. Glancing or reversed hits are trimmed down to a minimum factor. Spinners stay omnidirectional — a whirling bar hits with whatever edge meets the enemy.

At runtime CombatHitDealer.WeaponContactDamage layers it all on top of the solver impulse: impulse sets the energy, the profile scales it, armour hardness blunts piercing, and the directional factor trims off-axis blows. Frame-welded static weapons are tagged with a WeaponSurface so the chassis dealer upgrades their contacts from a generic ram into a real, directional strike.

Reach: motor → extender → implement

Spinners that need to clear the chassis don't cheat their geometry — they chain a weapon motor to an extender to an implement. A horizontal spinner lifts its bar on an extender; a vertical spinner instead raises its motor on a bracket (an extender would push the disc sideways, not up). The shipped Vertical Saw demonstrates the correct floor clearance.

Actuated weapons: flippers & hammers

Not every weapon spins. Flippers, hammers, and the overhead axe are hinged to the chassis and driven on command rather than run continuously. Each parks at a rest pose, and a fire input swings it through its stroke and back, then re-arms — a state machine (Idle → Firing → Holding → Returning) in WeaponController drives the hinge motor to the target angle for each phase.

  • Flipper — a low plate at the nose, hinged at its rear edge. Firing whips the front edge up; on top of the contact damage it hands the victim a mass-scaled upward launch impulse at the strike point, so a foe that drove onto it is flung up and over rather than just nudged.
  • Hammer / Overhead Axe — a tall arm that stands cocked over the deck and slams its head forward and down onto a foe in front. The axe carries a sharper, lighter head that bites as it chops; the hammer leads with blunt concussion.

Fire with Space (the same key spins a spinner up). The AI (EnemyAIController) fires automatically when an opponent is inside a heading cone and close enough to connect, so flipper and hammer bots fight themselves in AI-vs-AI. A fired hinge reads its angle straight from the solver, so the swing is honest physics — the same launch and slam are pinned by the live-physics playtests in Testing.

Power Budget

Power is checked on two axes — voltage and wattage — just like a real combat robot.

  • Voltage: motors declare a nominal and max voltage. Overvolting (e.g. 12 V motors on a 24 V pack) buys speed but must be within the motor's max.
  • Wattage: batteries advertise a peak output (W); motors a peak demand. BotStatsCalculator sums both and the stats panel shows peak / output W.

If your motors can out-pull your packs, the validator raises an advisory warning (the RA2 “brown-out under load” rule) — it won't block the build, but the fix is a bigger or extra battery.

Rule of thumb: the small NiMH pack runs a pair of drive motors; a 24 V spinner build wants the large LiPo pack. Stacking heavy motors on a small pack trips the warning.

The Garage

The garage is a physics test arena. Drive your bot, spin its weapon, summon an opponent, and watch parts come apart under real impacts.

Garage combat with victory banner
The combat HUD: per-bot health bars, drive/weapon telemetry, on-screen controls, and a knock-out banner.

Controls recap

WASD Drive Space Spin / fire weapon Q/E Throttle weapon Tab Arcade / Tank R Respawn F Spawn / remove enemy P Autopilot C Camera

Impacts spark and clang, weapons whir as they spin up, and a knock-out triggers a blast, smoke and a stinger. Press F to spawn a sparring opponent at any time, or R to repair and respawn your bot.

Localized Part Damage

Combat is more than one health bar. Alongside the whole-bot knock-out pool, each independent sub-part — every wheel, each weapon assembly, exposed wedges and spikes — carries its own DamageableBody. Focused punishment cripples a component long before the bot dies.

🛞

Wheels degrade, then break off

A worn wheel makes less torque and tops out slower (the bot pulls to one side). Past a threshold the tyre pops — grip is cut and you see a squash. At zero it tears off its axle and tumbles away as debris.

🌀

A damaged spinner spins you out

Every hit a weapon lands wears itself, and incoming hits damage it directly. A worn weapon becomes unbalanced: it shoves the chassis with a force scaling with the square of spin speed. Ease the throttle (Q) to tame the wobble — the HUD warns ! UNBALANCED.

🔥

Parts smoke, electrics burn

Beaten parts trail rising smoke; a failing battery or motor catches fire. Internals couple to the bot's overall health, so a dying machine cooks from the inside. A torn-off part keeps burning as debris before guttering out.

💥

Debris & banners

Destroyed parts emit their own blast / smoke / boom and flash a HUD banner (WHEEL TORN OFF!). The control board is spared so a bot can't be cheaply disabled.

A battle-worn bot trailing smoke with gash decals
A battle-worn hero: real dents, gash/scuff decals, and looping smoke from a beaten weapon.

The whole system is gated by BuildBattleSettings.enablePartDamage (turn it off for indestructible parts), wobble by weaponWobbleScale, and smoke/fire by enableDamageFx. The balance numbers live in one testable place: CombatMath (PartHpScale, WheelPopFraction, PoppedWheelGrip, WeaponSelfWearFraction).

Camera & AI vs AI

The arena camera

A single BattleCamera offers five views, cycled with C: two fixed broadcast vantages (Wide, Ringside) that pan to track the action, and three chase distances (Far, Mid, Close — scroll to fine-zoom). It's built to stay watchable under chaos:

  • It follows a smoothed focus point, and the chase heading comes from the bot's velocity, not its orientation — a rammed or flipped bot won't whip the view around.
  • Rotation is always built against world-up, so the horizon stays level even when the bot rolls.
  • Impact shake is small and tunable: set cameraShakeScale to 0 for a rock-steady view.

Watch AI fight AI

Press P (or the Autopilot button) to hand your bot to the AI. It spawns an opponent if needed, switches to the broadcast camera, and lets two evenly-matched AIs fight while you spectate — same brains, drivetrain and weapons on both sides. Press P again to take back the wheel.

The AI (EnemyAIController) is physics-honest: it reads the target's position and writes arcade input into the same drive controller you use — it never teleports. Because it's generic, the garage can attach it to either bot, which is exactly how AI-vs-AI works.

Paint Shop

The Paint Shop step finishes a bot's look — and combat then marks it up for real. It's the same data-driven model as everything else, surfaced four ways.

Paint

A row of standard colours is washed over the chosen armour material rather than replacing it, so steel still reads as steel — just painted. Purely cosmetic (no mass or durability change), saved as a single paintId.

Bare Armour Racing Red Inferno Orange Hazard Yellow Combat Green Toxic Lime Cyan Cobalt Blue Royal Purple Hot Pink Gunmetal Jet Black Arctic White

Stickers & livery

Pick a decal and it ghosts onto the shell, snapping flush to the surface. Place controls:

Scroll Resize R / Ctrl-scroll Rotate Left-click Stick (keep placing) X / Del Peel one off
Cooling Vent Hazard Stripes Star Flame Roundel Arrow Bolt Hole (mask) Weapon Slot (mask)

Functional hole / slot masks

Two stickers read as a bored hole or a machined slot cut into the armour. Place one where a spinner shaft or weapon extender passes through the wall and the spot reads as designed — a clean fix for the inside-out builder's unavoidable pass-throughs, instead of a weapon appearing to clip through solid metal.

Armour that dents (mesh deformation)

Wear marks are painted on; the dents are real geometry. Every blow that lands on the shell pushes its mesh vertices inward along the surface — a blunt ram leaves a broad bowl, a sharp disc or axe carves a tight, deep gash, and repeated hits along a path accumulate into a torn channel. The deformation is permanent for the life of the bot, so a shell visibly crumples over a fight. Only the rendered mesh is reshaped (and refined on the fly so dents read smoothly across a panel) — the bot keeps its original convex collision hull, so denting never destabilizes the physics solver. Gated by BuildBattleSettings.enableDeformation.

Battle scars (automatic)

During a fight the combat system sprays a wear mark wherever a weapon bites, chosen by how sharp the blow was:

gash — a bright torn cut (disc/axe) scuff — a grey glancing mark scorch — a dark blunt burn crater — a heavy blunt dent ring

Each mark normalizes onto the exact piece the blow struck — the shell, a wheel, or a weapon — parented to that part's transform and oriented to its surface, so a hit on a tyre scars the tyre, not the air beside it. Marks carry no colliders (they never disturb physics) and are oldest-recycled so a long fight stays cheap. Decals are flat, unlit, double-sided transparent quads sharing one material per texture key, with art generated procedurally and baked to Resources/Decals/*.png.

Hit marks honour BuildBattleSettings.enableHitDecals; player stickers are unaffected. Adding a paint colour, sticker, or hit effect is a one-catalogue edit — see Extending the Kit.

Audio & FX

Sound and particles are procedural-first with bakeable assets, mirroring the rest of the kit.

BBSfx — synthesis

Every cue is synthesised from math — impacts, the looping weapon whir, knock-out boom, UI click, win/lose stingers — and can be encoded to 16-bit PCM .wav. Deterministic (seeded), so bakes are reproducible.

BBAudio — playback

A tiny runtime player: pooled 2-D sources for one-shots and a Loop(...) helper for the whir that rides the bot. Resolves baked clips first, falls back to live synthesis.

BBVfx — particles

Spawns named effect prefabs (sparks, KO blast, smoke), tints and auto-destroys them, and hosts the looping damage emitters (FX_Fire, FX_DamageSmoke) that beaten parts drive.

BuildBattleSettings

One inspector gates master / SFX / whir volume and the audio & FX on/off switches — rebalance the whole kit with no code.

Sample Bots

Nine ready-to-drive presets ship with the kit — researched after the archetypes from the Robot Arena series and real combat robots: horizontal and vertical spinners, an overhead axe, a hammer, a flipper, and control bots. Every one is fully hand-buildable in the workshop. Click any image to enlarge.

The wide-stance look

Drive motors sit at the corners and a fat tyre seats half its width outboard of the axle face, so wheels stick proud of the shell — the aggressive monster-truck stance real combat robots have, which also lowers the ground line for spinner clearance.

Bar Spinner side profile showing wheel stance
Side profile: wheels protrude past the shell for a planted, wide stance.

Presets live in BotPresets.cs and are built through the same BotAssembler a player's placements go through. To add your own, see Extending the Kit → Add a pre-made bot.

Developer Tools

Everything lives under the BuildBattle menu in the Unity editor. The Hub is your front door; the rest are one-click bakers and capture rigs.

Menu itemWhat it does
Tools ▸ BuildBattle ▸ HubThe front-door window: open scenes, bake, capture, jump to settings, open these docs. Auto-opens once per session.
Tools ▸ BuildBattle ▸ Authoring ToolsA workbench that scaffolds ready-to-paste C# for a new component or bot, opens any catalog in one click, and runs the bake / verify loop.
Tools ▸ BuildBattle ▸ Create Scenes(Re)generates the playable Workshop & Garage scenes.
Tools ▸ BuildBattle ▸ Open Workshop SceneOpens the build wizard scene.
Tools ▸ BuildBattle ▸ Add Entry To Current SceneDrops the BuildBattle entry point into the open scene.
Tools ▸ BuildBattle ▸ Bake Asset LibraryProjects all procedural content into inspectable assets: prefabs, shared materials, meshes, .wav sounds, FX prefabs, and the Demo/Showcase.unity scene.
Tools ▸ BuildBattle ▸ Bake Sounds && FXRegenerates just the audio + FX prefabs + settings asset.
Tools ▸ BuildBattle ▸ Capture Bot ScreenshotsHero + side shot of every preset (headless, to Screenshots/).
Tools ▸ BuildBattle ▸ Capture FX PreviewA frozen particle-FX preview frame.
Tools ▸ BuildBattle ▸ Capture Feature ReelThe full set: build progression, battle-worn hero, launch burst, interior cutaways, UI shots, and AI-vs-AI video.
Tools ▸ BuildBattle ▸ Capture Battle-Worn HeroJust the deformation + damage-texture hero shot (dents, gash/scorch decals), headless to Screenshots/feature/.
Tools ▸ BuildBattle ▸ Capture AI Battle VideoJust the AI-vs-AI fight (frames + mp4 if ffmpeg is on PATH).
Tools ▸ BuildBattle ▸ Capture UI ScreenshotsThe workshop & garage HUDs composited over a bot.
Tools ▸ BuildBattle ▸ Capture Scene Previews / Capture ShowcaseRenders the scenes / the showcase to Screenshots/ for a quick visual check.

This very document was generated by the docs build script in Assets/BuildBattle/Documentation/, which embeds the latest captures from Screenshots/latest. Re-run it after capturing new media to refresh the screenshots.

Extending the Kit

BuildBattle is code-first and data-driven: one registry of part types is the single source of truth, and the palette, placement rules, physics, save files and baked prefabs are all derived from it. Adding content is a small catalog edit that flows through the whole kit.

The one mental model

PartCatalog (register a PartDefinition)
   │  the id is the only thing a save file stores
   ▼
PartFactory.BuildDetailedVisual  ──►  a primitive mesh + ONE root collider
   │
   ├──► Workshop: appears in the palette, snaps to grid/sockets, collision-checked
   ├──► Stats / Validation: counted toward mass, power, legality
   ├──► BotSpawner: rebuilt as a rigidbody / hinge / weld in the garage
   └──► BBAssetBaker: persisted as Prefabs/Parts/<id>.prefab

You almost never edit more than the catalog and (optionally) the factory.

Where to edit, by task

To add…Edit…
A componentCore/Parts/PartCatalog.cs (register a PartDefinition); optional visual in PartFactory
A weapon (with its bite)PartCatalog.cs — give the WeaponDefinition a WeaponDamageProfile
An armour materialCore/Materials/MaterialManager.cs (density, durability & hardness)
A pre-made botCore/Presets/BotPresets.cs via BotAssembler
An enemy archetypeCore/Combat/EnemyBotFactory.cs (also via BotAssembler)
A weapon-reach partPartCatalog.cs — an ExtenderDefinition
A paint colourCore/Decals/PaintCatalog.cs
A sticker / hit-effectCore/Decals/DecalCatalog.cs + a shape in BBDecalTextures.cs
A soundCore/Audio/BBSfx.cs (synth); play via BBAudio.Play(...)
A particle effectEditor/BBContentBaker.cs; spawn via BBVfx.Spawn(...)
Re-tune combatCore/Combat/CombatMath.cs + BuildBattleSettings.asset

After changing any catalog, re-run Tools ▸ BuildBattle ▸ Bake Asset Library so the inspectable assets match the code.

Recipe · Add a component

A worked example — a capacitor bank (just mass + looks). Add one line to PartCatalog:

new StructuralDefinition("cap_bank", "Capacitor Bank", 1.8f,
    new Vector3(0.09f, 0.06f, 0.07f), 30f, new Color(0.30f, 0.32f, 0.40f)),

That alone makes it appear in the palette, snap to grid, get mass-counted, validate, spawn in the garage, and bake to Prefabs/Parts/cap_bank.prefab. The constructor families:

new ControlBoardDefinition("board_x", "...", m, dims, hp, drawW, tint);
new BatteryDefinition("battery_x", "...", m, dims, hp, wh, volts, maxW, cylindrical:false, tint);
new DriveMotorDefinition("motor_x", "...", m, dims, hp, torque, rpm, drawW, tint, 12f, 24f);
new WheelDefinition("wheel_x", "...", m, r, w, hp, friction, tint);
new WeaponMotorDefinition("wmotor_x", "...", m, dims, hp, torque, rpm, drawW, Vector3.up, tint, 24f, 36f);
new StructuralDefinition("ballast_x", "...", m, dims, hp, tint);

To give it a recognisable look, add a case to PartFactory.BuildDetailedVisual(...). Keep the collider a single authoritative box/capsule/sphere on the root — never on visual children.

Recipe · Add a weapon

Weapons also describe how hard they hit. Use a ready-made profile or build your own:

WeaponDamageProfile.Spinner(piercing, concussion); // omnidirectional, sharp-ish
WeaponDamageProfile.Blunt(concussion, piercing);   // omnidirectional, blunt
WeaponDamageProfile.Wedge();                        // directional, forward/up, blunt
WeaponDamageProfile.Spike();                        // directional, dead-ahead, sharp
WeaponDamageProfile.Axe();                          // directional, forward-and-down chop
WeaponDamageProfile.Hammer(concussion, piercing);  // heavy slam (hammer / overhead axe)
WeaponDamageProfile.Flipper();                      // light blunt — the launch does the work

A spinning implement bolts onto a weapon mount (default):

new WeaponDefinition("weapon_flail", "Chain Flail", 1.6f,
    new Vector3(0.06f, 0.06f, 0.30f), 55f, new Color(0.7f, 0.7f, 0.75f),
    WeaponDamageProfile.Blunt(concussion: 0.6f, piercing: 0.2f),
    PrimitiveShape.Bar),

A static, frame-welded weapon bolts to the floor — set the parent socket:

new WeaponDefinition("weapon_plow", "Forged Plow", 2.4f,
    new Vector3(0.26f, 0.06f, 0.18f), 70f, new Color(0.6f, 0.62f, 0.68f),
    WeaponDamageProfile.Wedge(), PrimitiveShape.Box, SocketType.ChassisFloor),

An actuated weapon adds an actuation type and hinge parameters — it's mounted to the chassis floor and swung by WeaponController, not welded. A flipper also carries a launchSpeed for the mass-scaled fling:

new WeaponDefinition("weapon_flipper", "Flipper Plate", 2.2f,
    new Vector3(0.30f, 0.05f, 0.22f), 70f, new Color(0.66f, 0.68f, 0.74f),
    WeaponDamageProfile.Flipper(), PrimitiveShape.Flipper, SocketType.ChassisFloor,
    WeaponActuation.Flipper, hingeLocalAnchor: new Vector3(0f, 0f, -0.11f),
    hingeAxis: Vector3.right, swingDegrees: -72f, swingSpeedDegPerSec: 620f,
    swingTorqueNm: 220f, launchSpeed: 4.2f),

Vertical-spinner geometry caveat: a vertical motor's mount axis is lateral, so an extender pushes the disc sideways, not up. To raise a vertical disc, raise the motor with a heightOffset (a real bearing bracket) — never an extender. The shipped Vertical Saw shows the pattern.

Recipe · Add an armour material

[MaterialType.Carbon] = new ArmorMaterial(
    MaterialType.Carbon, "Carbon Fibre", 1600f, 1.3f, 0.004f,
    new Color(0.12f, 0.12f, 0.14f), 0.2f, 0.6f, 120f),
//   type, name, density, healthMult, shellThickness, tint, metallic, smoothness, hardness

Add the enum value to MaterialType first. The workshop's material step and the weight calc pick it up automatically. Hardness resists the piercing share of hits.

Recipe · Add a pre-made bot (kept hand-buildable)

Author through BotAssembler — a “virtual workshop” that obeys the exact placement rules the live UI enforces:

private static BotDefinition BuildHammerBot()
{
    var def = NewChassis("Hammer", MaterialType.Steel);
    var b = new BotAssembler(def);

    AddCornerDrive(b);                  // 4 corner motors, one wheel each
    b.Floor("board_basic", 0f, -0.15f); // x, z on the 0.05 m grid
    b.Floor("battery_large", 0f, -0.05f);

    string wm = b.Floor("wmotor_spinner", 0f, 0.10f);   // weapon motor on the floor
    string ex = b.Attach("extender_long", wm, "mount"); // extender onto the mount
    b.Attach("weapon_bar_long", ex, "tip");             // implement onto the tip
    return def;
}

Then register it in the _all preset list with a name and one-line blurb. The API:

  • Floor(id, x, z, heightOffset = 0, euler = default) — drops a floor part; snaps to the grid, rests on the baseplate, then raises/tilts.
  • Attach(id, parentInstanceId, parentSocketId) — bolts a child onto a real socket, refusing a wrong type or a double-booked socket.

The five rules every bot must satisfy (enforced by tests)

  1. Sockets are real, correctly typed, used at most once.
  2. Attachments sit exactly where SocketSnap would put them.
  3. Floor parts are grid-snapped & bounded; weapons may overhang (only their anchor centre must be over the frame), internals may not.
  4. No two parts clip (OBB separating-axis test).
  5. Spinning weapons clear the floor (lowest point ≥ 4 cm above the wheel-contact plane).

Recipe · Add an opponent & its AI

Add a value to EnemyArchetype and a builder (just like a preset), branch to it in Create(...), and add it to PresetBuildabilityTests.AllBots(). The brain is generic and wires up in one line:

// GarageBootstrap.SpawnEnemy()
_enemyAI = _enemy.Root.AddComponent<EnemyAIController>();
_enemyAI.Initialize(_enemy.Drive, _enemy.Weapon, _enemy.Health, _bot.Health);

Tunable knobs: SteerFullLockDegrees (heading error → full lock) and EngageDistance (how close it presses before grinding).

Recipe · Add paint, a sticker, a sound, an effect

// Paint colour — PaintCatalog.cs
new PaintColor("battleship_grey", "Battleship Grey", new Color(0.40f, 0.43f, 0.46f)),

// Sticker / hit effect — DecalCatalog.cs (+ a shape in BBDecalTextures.Sample)
new DecalDefinition("sticker_skull", "Skull", DecalCategory.Sticker, "skull",
    0.06f, Color.white, false, "Pirate skull marker."),

// Sound — BBSfx.cs, then play anywhere
BBAudio.Play(BBSfx.Servo, volumeScale: 0.8f, pitch: 1.1f);

// Particle effect — BBContentBaker.cs, then spawn
BBVfx.Spawn(BBVfx.Spray, contactPoint, tint: Color.cyan, scale: 1f);

Ship checklist

  1. Register the part/material in its catalog; add a PartFactory visual if you want it recognisable.
  2. For weapons, give a WeaponDamageProfile; for nose spinners, mind floor clearance.
  3. Add bots/enemies through BotAssembler and list them in the buildability test.
  4. Tools ▸ BuildBattle ▸ Bake Asset Library (or Bake Sounds && FX).
  5. Run the EditMode tests until green.

The full, worked manual is Documentation/AUTHORING_GUIDE.md — this section is the fast index.

Capturing Media

Two headless rigs render straight to Screenshots/ with an offscreen camera — no play mode, no manual scene. Run with a GPU (do not pass -nographics).

  • BBShots (Capture Bot Screenshots / Capture FX Preview) — a hero + side shot of every preset and a frozen FX preview.
  • BBReel (Capture Feature Reel) — the full set: a workshop build progression, interior cutaways, a battle-worn hero (real dents + decals + staged smoke/fire), a spinner-launch burst, UI shots, and an AI-vs-AI battle captured frame-by-frame.

The battle recorder spawns two bots, attaches an EnemyAIController to each, and steps a manual Physics.Simulate loop — driving the real brains, drivetrain and weapons through their public tick hooks, so the footage is genuine physics, not a canned animation. If ffmpeg is on your PATH it also encodes an .mp4.

Unity.exe -batchmode -projectPath <proj> \
  -executeMethod BuildBattle.EditorTools.BBReel.CaptureAll -logFile reel.log -quit

Set the BB_SHOT_DIR env var to redirect the output folder. Editor windows (Hub, Authoring Tools, the wizard HUD) aren't rendered by these rigs — grab those with an OS screenshot.

Testing & Verification

A large EditMode suite covers chassis geometry, validation, serialization (including the paint + sticker round-trip), stats/voltage, the combat damage model, the catalogue, presets, the paint shop, battle damage FX, the controller step hooks, audio synthesis, and the actuated weapons — including a live-PhysX playtest that spawns the flipper, hammer and axe, fires them, and asserts the plate really lifts and the heads really slam forward and down.

Run from Window ▸ General ▸ Test Runner ▸ EditMode, or headless:

Unity.exe -batchmode -projectPath <proj> \
  -runTests -testPlatform EditMode -testResults results.xml

Buildability is verified, not asserted. PresetBuildabilityTests replays the workshop's checks over every preset and enemy: real/typed sockets, exact snap placement, grid + bounds, OBB clip checks, and spinning-weapon clearance — both that a spinner clears the floor and that it dips low enough to actually strike a foe. A failing buildability test is a feature — it means a player couldn't make the thing you shipped.

Reference Tables

Weight classes

Set def.weightClass on the chassis; the validator checks total mass against the cap.

ClassCodeMax mass
AntweightAW≤ 125 kg
BeetleweightBW≤ 175 kg
LightweightLW≤ 249 kg
Middleweight defaultMW≤ 399 kg
CruiserweightCW≤ 600 kg
HeavyweightHW≤ 800 kg
Super HeavyweightSHW≤ 1200 kg
Ultra HeavyweightUHW≤ 5000 kg
Giga HeavyweightGHW≤ 10000 kg

Tune feel without code — BuildBattleSettings.asset

FieldEffect
masterVolume, sfxVolume, weaponWhirVolumeAudio mix
enableAudio, enableVfxMaster switches
impactSparkColorSpark tint
enablePartDamageLocalized part damage / detachment on/off
enableHitDecalsSpray scorch/scuff/gash/crater marks (stickers unaffected)
enableDamageFxSmoke from beaten parts + fire from failing electrics
weaponWobbleScaleHow violently a damaged spinner shakes the bot
cameraShakeScaleImpact shake (0 = rock-steady)

Keyboard reference (garage)

WASD Drive Space Spin up weapon Q Weapon slower E Weapon faster Tab Drive mode R Respawn F Spawn / remove opponent P Autopilot (AI vs AI) C Cycle camera Scroll Zoom (chase views)

Assemblies

BuildBattle.Core ──► BuildBattle.Workshop / .Physics / .UI ──► BuildBattle.App
                     + BuildBattle.Editor (editor-only)
                     + BuildBattle.Tests  (EditMode)

The clean dependency graph keeps gameplay code free of editor and UI concerns.

Folder structure

Assets/BuildBattle/
├── Scripts/          Runtime code (asmdef per folder)
│   ├── Core/         Data, parts, chassis, materials, stats, validation, presets, audio, fx, decals
│   ├── Workshop/     Build-mode controllers (grid, placement, gizmos, selection)
│   ├── Physics/      Garage sim (spawner, drive, weapons, health, combat, AI, damage fx)
│   ├── UI/           Procedural uGUI HUDs + the UI factory
│   └── App/          Entry point, scene flow, ArenaFactory, BattleCamera
├── Editor/           Hub, Authoring Tools, scene builder, bakers, capture rigs
├── Tests/            EditMode unit tests
├── Resources/        Baked textures, audio, FX, decals, settings asset
├── Prefabs/          Baked parts, bots, environment
├── Scenes/           Workshop.unity, Garage.unity
├── Demo/             Showcase.unity (authored from baked prefabs)
└── Documentation/    README, AUTHORING_GUIDE, this handbook

For the deepest detail, read Documentation/BuildBattle_README.md (using the kit) and Documentation/AUTHORING_GUIDE.md (extending it). This handbook distills both.