Skip to content

Animation

How Massive Swarm System animates agents, and how to pick the right approach for your target hardware.

Choosing an approach

Approach Best for Cost
VAT (Vertex Animation Texture) Mobile, 1000+ agents Very low
Animator + SwarmAgentAnimation Richer character animation at lower counts Medium to high (skinned mesh)
No animation component Rigid-body enemies, simple shapes Minimal

VAT Animation

VAT bakes skeletal animation into a texture. At runtime the agent mesh samples the texture to reconstruct vertex positions: no skeleton, no SkinnedMeshRenderer, no per-bone CPU work.

VAT agents use VatAnimator (added to the prefab), which SwarmVisualManager drives each frame. Each agent keeps its own MeshRenderer. The generated VAT material has GPU instancing enabled and the per-agent state travels in the instancing buffer, so Unity batches the identical draws automatically. The VAT baker window is at Tools → Massive Swarm System → VAT Baker.

When to use VAT: targeting mobile, or when skinned mesh cost is visible in the profiler at your target agent count.

When not to use VAT: when you need real-time bone manipulation, IK, or procedural animation that cannot be pre-baked.

VAT bake workflow

  1. Assign a source skinned mesh prefab and animation clips in the VAT baker window.
  2. Click Bake VAT Prefab. The baker generates a .asset (VAT data), a .mat (VAT material), and a ready-to-use prefab.
  3. Assign the generated prefab to the agent archetype.
  4. At runtime, SwarmVisualManager updates each agent's VatAnimator, which writes that agent's clip and tint data into its MeshRenderer through a MaterialPropertyBlock. Because the VAT material has GPU instancing enabled, Unity batches the draws.

VAT Baker field reference

Open the baker at Tools → Massive Swarm System → VAT Baker. The window has a Simple / Advanced toggle and a Single Prefab / Batch toggle at the top.

Simple mode walks you through four numbered sections and hides advanced overrides. Advanced exposes clip loop flags, sample rate, and the normal-bake toggle. Use Simple for everyday bakes; switch to Advanced only when you need to override the preset's defaults.

Single Prefab bakes one source at a time. Batch bakes a list of prefabs that share the same clips, preset, and output folder. Each prefab writes its own named VAT asset.

Section 1: Source Prefabs

Field What it does
Model Or Prefab The prefab, model asset, or scene object that contains the source skinned renderer. Drag directly into the drop zone or use the object field.
Source Renderer The body anchor: the SkinnedMeshRenderer whose material becomes slot 0. Auto-set to the highest-vertex skinned mesh. Other skinned meshes on the character bake in alongside it. See Multi-part characters.
Avatar Avatar used by the temporary sampling Animator. Required for humanoid clips when the source has no Animator with an Avatar of its own.

Batch mode shows an additional Avatar field labeled Shared / Fallback Avatar. Prefabs in the batch that already carry their own Animator + Avatar use their own; the fallback only applies to prefabs without one (typically FBX models imported without a rig). Use Auto Fill to pick the first available avatar from the batch list.

Section 2: Animation Clips

Field What it does
Idle Looping idle animation. Required for the agent to stand still.
Walk Looping locomotion clip at walk speed.
Run Looping locomotion clip at run speed.
Attack (Optional) Optional one-shot attack clip. When baked, VatAnimator.TryPlayAttack() plays it at runtime, and the baker measures when its blow lands and stores it as the asset's Hit Time. Leave empty if the archetype has no attack animation.
Death (Optional) Optional clip played once when the character dies, holding its last frame. An agent that dies with a dissolve plays it first and only then fades, so the body falls and lies still before it disappears. Always one-shot, so there is no Loop toggle. Leave it empty and a death looks as it did before: the dissolve starts at once.

Use Auto Find Clips to scan the source asset, its Animator Controller, and the current selection for clips named like idle, walk, run, attack, or death.

A dying agent stays on screen for the length of the death clip plus the dissolve. The dissolve is set on the component that kills the agent, for example Death Dissolve Duration on the StarterKit's Swarm Agent Combat Target. If that is 0, the agent disappears at once and the death clip does not play.

In Advanced mode, a Loop toggle appears inline for each clip. Simple mode keeps all locomotion clips looping and the attack clip one-shot, matching the expected runtime behavior for most archetypes.

Attack clip loop flag

The attack clip defaults to non-looping (one-shot). Enable the loop toggle in Advanced mode only for channeled attacks. A looping attack clip started with TryPlayAttack repeats forever and locomotion cannot take over, because the attack has no end time to pass. Call StopAttack() to end it. Returning the agent to the pool also clears it.

Bake In Place

Some clips move the whole character across the ground: a walk exported with its travel still in it, or an attack that lunges forward. An agent is moved by its own code, so that travel plays on top of the agent's movement. The mesh drifts away from where the agent is and snaps back when the clip restarts.

When the baker finds a clip like that, a Bake In Place checkbox appears under it, in both Simple and Advanced mode, with the bone that carries the travel and how far it goes in units. A clip that already stays in place gets no row. Tick it and the clip is baked without its horizontal travel. Vertical motion, such as the bob of a walk or the height of a jump, is baked as authored. Left unticked, the clip bakes exactly as earlier versions baked it.

On the Walk and Run slots the baker removes only the steady part of the travel, the straight line from the first frame to the last. A shambling walk that lurches forward and slows down inside each step keeps that rhythm, and because the playback speed follows the agent's speed, the planted foot stays on the ground instead of sliding. Idle, Attack and Death are pinned to where the clip starts, so a lunge ends where it began.

A walk or run that ends away from where it started makes the agent slide backwards on every loop, so those two clips also get a warning with a Bake In Place button. A clip whose hips sway and come back, or an attack that lunges and returns, gets the checkbox without the warning.

The choice is saved into the baked asset, so rebaking it later, alone or in a batch, applies it again. The asset's Clip Table marks the clip In Place.

What counts as travel

The baker looks at the top bones of the rig, the root and up to three levels down, which is where the hips sit in Mixamo, Meshy and Blender exports. Movement that is small next to the character's height is treated as sway and ignored. Humanoid clips are covered too: their travel is read from the Avatar's root motion and removed from the hips.

Facing forward

An agent moves along its own forward direction, +Z, so its walk has to head that way too. Some clips arrive facing the other way. The Quaternius Universal Animation Library, retargeted onto a rig that faces +Z, plays facing -Z, in Unity's own Animator as well as in a bake, and agents built from it walk backwards.

The baker checks for this after it samples the clips. It reads which way the walk heads from the feet (a foot travels forward while it is lifted and comes back along the ground) and turns the whole bake by the nearest quarter turn so the walk heads toward +Z. Every clip gets the same turn. A clip whose first pose faces the opposite way from the walk's, which happens when the walk and the attack come from two different packs, gets a further half turn. The bake report lists what was turned, and the asset's Clip Table marks those clips. A bake that already faces +Z is not touched.

It needs a walk or run clip. Without one, or when the feet do not agree on a direction (a creature with no clear feet, a shuffle that never lifts them), the bake is left as sampled and the report says so.

Auto Face Forward is on for every new bake and sits in Advanced Bake Settings. An asset baked before the option existed rebakes with it off, so a character you already turned by hand, for example by rotating its prefab's Visual child, keeps its facing. The report still tells you when its walk heads away from +Z. Turn the option on and remove your own rotation to hand the job to the baker.

Why the import settings don't fix it

Unity's usual fix for a humanoid clip that faces the wrong way is Root Transform Rotation → Based Upon: Body Orientation in the clip's import settings. It works in Unity's Animator, but the baker samples clips with AnimationMode.SampleAnimationClip, which ignores it, so the bake keeps the old facing. Auto Face Forward works on the sampled result and does not depend on that setting.

Advanced Bake Settings (Advanced mode only)

Field What it does
Sample Rate Frames sampled per second for each clip. Range 1 to 60. Lower values reduce texture size; higher values preserve fast motion. For clips used as slower-playback fallbacks (walk/run), the baker automatically raises the effective sample rate proportionally to maintain visual quality.
Bake Normals Bake animated normals into a second texture for lit shading. Doubles the texture memory cost. Disable this on mobile to reduce GPU bandwidth.
Auto Face Forward Turns the bake so the walk heads toward +Z, the way the agent moves. On for a new bake, off when rebaking an asset made before the option existed. See Facing forward.

In Simple mode these settings are driven by the selected Preset. Switch to Advanced only when you need to override them.

A looping clip whose sampled last frame would repeat the first is trimmed by that frame, so a rebake can come out one frame shorter than it used to. A one-shot clip always keeps its last frame, since that is the pose it has to end on.

Section 3: Output

Field What it does
Output Folder Asset-relative folder where the .asset, .mat, and prefab are saved. Use Pick Folder to browse, or Use Default to go back to Assets/VAT. Baked output lands outside the package on purpose, so updating Massive Swarm System never touches it.
Create VAT Material Create a material wired to the baked VAT asset using the package VAT shader. Disable only if you have a custom material pipeline.
Create Ready Prefab (Simple mode) Also output a prefab pre-wired to the baked asset and material. Disable to get raw VAT assets for a custom pipeline.
Update Linked Material (rebake only) Refresh the existing linked material in place so renderers keep their material reference rather than pointing at a new file.

Section 4: Ready to Bake (Simple mode)

This section shows the estimated GPU cost (total texture size and vertex count) from the baked vertex count (the body plus every included part), sample rate, and total clip duration. The status pill rates that cost against the selected preset's budget, not one fixed limit. Mobile holds a tight budget, the same one that keeps a 1000+ swarm affordable on a phone; Standard and High allow progressively larger bakes for desktop crowds and hero shots. Green means within budget. For a single bake, amber covers both heavy and oversized for the chosen tier, and red is reserved for a bake the GPU cannot store at all, when the vertex count or frame count exceeds the platform's maximum texture size. A batch shows its worst character, and there oversized reads red. The same bake can read oversized on Mobile and green on High, so pick the preset that matches how the character will be used, then check the estimate.

Click Bake VAT Prefab (or Bake VAT if prefab output is disabled) to run the bake. The baker writes the generated assets to the output folder and shows a report in the section below.

Every bake also measures how the walk and run clips step. The report's Steps: block names what it found for each: how fast the clip covers ground, where that number came from, and how many strides one loop holds. The VatAsset inspector's Walk And Run section, further down this page, covers what those numbers mean and what to do when one could not be measured.

Bake presets

The Bake Preset dropdown (collapsed by default in Simple mode) selects from three built-in presets. Each preset sets the sample rate, normal-bake flag, and the tier render shader together. Choose the preset that matches your target platform, then override individual settings in Advanced mode only if the preset is not quite right.

Preset Description
Mobile Cheapest tier for the big crowd. Skips the normal texture, so shading is flatter at distance. That is the right trade for 1000+ swarms and on-device builds.
Standard Balanced default. Full surface detail (normal, metallic, occlusion) lit by the main light with soft shadows. Good for hundreds of agents on desktop.
High Showcase tier. Adds dynamic point and spot lights plus their shadows on top of Standard. For hero shots and small counts. Reflection probes already work on Standard, so that is not what you are buying here.

See VAT Render Quality Tiers for a full breakdown of what each tier costs and when to switch.

Quickstart: typical bake steps

  1. Select a preset that matches your target platform.
  2. Assign the source prefab (drag into the drop zone).
  3. Assign clips. Use Auto Find Clips first.
  4. Confirm the memory estimate looks reasonable for your target.
  5. Click Bake VAT Prefab.

After the bake: the VatAsset inspector

The baker writes a VatAsset, and selecting it gives you a working panel rather than a dump of serialized data. This is where you go weeks later when you need to know what a bake actually contains, or when the source character has changed.

Stale State is the one to look at first. The asset records what it was baked from, and this box compares that against the project as it is now. Up to date says so plainly; if the source prefab, its clips, or its attachments have moved on since the bake, it turns into a warning that names what changed. It is the difference between "the animation looks wrong" and "the animation is from last Tuesday".

Clip Table lists every baked clip with its role, name, frame range, length in seconds, and whether it loops or plays once. Use it to confirm the baker assigned idle, walk, run and attack to the clips you meant. A clip baked in place says In Place, and one the baker turned to face forward says by how much.

Role Playback Multipliers are editable speed multipliers, one per role: Idle, Walk and Run, plus Attack when the asset has an attack clip. They exist for incomplete bakes. If a character has no walk clip, the baker falls back to the run clip at a 0.5 multiplier so it still reads as walking rather than sprinting on the spot. When the Idle, Walk or Run multiplier is not 1, the panel says so, which is your cue that a role is being faked. Tune them to make the substitution look deliberate.

Walk And Run holds the bake's measurements for the walk and run clips, and the place to correct one. Walk Clip Speed and Run Clip Speed are how fast the character has to travel, in units/second, for that clip's feet to hold the ground, with the clip at its baked speed and the object at scale 1. 0 means unknown. Playback uses them as the walk and run match speeds unless a VatAnimator on the prefab has Set Match Speeds By Hand turned on, which is covered in the field reference below.

Detect measures both clip speeds and the step timing from the baked frames and writes them to the asset. A value it cannot read is left as it was, and Undo puts back whatever it did write. It refuses outright, writing nothing, in three cases: no left and right foot found at the height of the pivot, the feet not moving in one clear direction, or the two feet not moving as a pair, which its message calls out as a weapon or a cloak likely hanging at foot height. A speed it can read but not cleanly, because the foot does not hold one speed while it is on the ground, is still stored and flagged as a rough reading worth checking in the preview below.

The Step Timing foldout holds Walk Strides Per Loop, Walk Stride Phase, Run Strides Per Loop and Run Stride Phase, which Detect fills in alongside the two speeds. They keep the walk and the run stepping on the same foot while they blend. Leave them alone unless the blend visibly steps on the wrong foot.

Preview On A Floor plays the character over a ruled floor at a speed you pick, a bright line every unit and a faint one every quarter unit. A foot carrying the body should ride its line. One that drifts over the lines means the match speed is not the speed the clip covers ground at. Play/Pause, Step to move on by one frame while paused, Slow for quarter speed, 3/4 View to look from the front and side instead of straight on, Walk and Run to jump the speed to the two match speeds, and a Speed slider. Here it plays at scale 1 with a VatAnimator's default settings; the same preview under the VatAnimator component's own inspector plays with that component's settings and at that object's scale. It runs outside Play mode only, adds nothing to the open scene, and is driven by the same playback code the game uses.

Attack Hit appears when the asset has an attack clip. Hit Time is the second, at the clip's baked speed, where the blow lands. The baker measures it: the frame where some part of the character has travelled furthest forward from where it started, with forward read from the walk clip, so it works whichever way the rig faces, including assets baked without Auto Face Forward. Type a value to correct it, or press Detect to measure it on an asset baked before it existed. 0 means unknown. An attack timed to its hit, like a swarm swing, plays the clip so this moment arrives with the damage; without a Hit Time the clip plays at its own speed. A rebake of the same attack clip keeps the value you typed.

Bake Provenance records completeness, the UTC bake timestamp, the baker version, a summary of the bake settings, and the tracked clips and attachments. Linked Outputs points at the source, material and prefab, each with a Ping button to find it in the Project window.

Actions carries the three buttons that do work:

  • Open Baker loads this asset's settings back into the VAT Baker window.
  • Rebake In Place re-runs the bake with the recorded settings and overwrites the asset, keeping its GUID. Prefabs, materials and scene references all survive, which is what makes it safe to re-bake a character mid-project. The button is greyed out, with the reason above it, when the model or a clip the asset was baked from is no longer in the project. Zombie City's MSS Zombie VAT is one of those: its source model is not in the package. The Egypt characters ship with theirs, so use one of them to try a rebake.
  • Create Or Update VAT Prefab builds the ready-to-use agent prefab from this asset, or refreshes the existing one.

Re-baking many assets at once

A VatBatch is a saved list of VAT assets, so you do not have to hunt them down one at a time when the character rig changes or you upgrade the package. Create one with right-click → Create → VAT Animator → VAT Batch and drop your assets into the list. Each row shows its own status, so an asset that cannot be rebaked says so before you press anything.

Two buttons, and the difference matters:

  • Rebake All re-runs every asset with the settings each one already recorded, after a confirmation dialog. Asset references stay stable. Assets without complete provenance are skipped rather than guessed at, and the button counts how many will actually run.
  • Open Baker With This Batch opens the VAT Baker in batch mode with every row linked to its existing asset. Use this one when you want to change a shared setting first, like sample rate, shader or normals, and then rebake the lot.

It has one other field: Fallback Avatar. Rebaking needs an Animator and an Avatar, and FBX models imported without a rig have neither. Assign a fallback here and those assets borrow it. Assets that already carry their own Animator and Avatar keep using theirs and ignore this field. If any asset in the list needs one, the inspector warns you and offers Auto Fill, which picks an avatar from the rigged prefabs already in the batch.

Multi-part characters

Most characters are more than one mesh. The body is often split across several SkinnedMeshRenderers (body, armor, skirt, shoulder pads) and weapons or cosmetics ride the bones as rigid MeshRenderers. The baker folds all of them into one VAT mesh, so the whole character animates from a single texture and renders in one draw, with no objects to sync at runtime.

Skinned parts. When the source has more than one SkinnedMeshRenderer, a Character Parts list is available under the Source section. In Advanced mode it is always shown. In Simple mode, open Show advanced source details to reach it, since that foldout starts closed. The highest-vertex mesh is the body anchor (marked Body); every other skinned mesh is listed with an include toggle, on by default. Untick a part to leave it out, or press Use as body to make a different mesh the anchor. They share the source skeleton, so each part deforms with the animation exactly as it does in the original prefab.

Weapons and attachments. A rigid weapon, shield, or cosmetic that sits on (or under) one of the character's bones bakes the same way, since it follows the bone for free. These appear in a separate Weapons & Attachments list. A mesh is eligible when it carries a MeshRenderer and MeshFilter and rides a bone of the body anchor. Both lists stay hidden when the character has none.

Materials and draw calls. The anchor's first material is slot 0. Every other distinct material across the baked parts gets its own slot, and parts sharing a material share a slot.

  • A part that uses the same material as the body adds no draw calls.
  • A part that needs its own material becomes one extra material slot: one extra draw call per agent. At a thousand agents that is a thousand extra draws, so share materials between parts where you can.

The Weapons & Attachments picker prints this running cost as you toggle parts. The Character Parts list does not, so if your character has extra skinned meshes and no bone-parented rigid meshes, read the Extra Draw Calls row in the Advanced mode Memory Estimate card instead.

The rest is free. Every part shares the body's position and normal textures and the same per-agent material property block, so tint, damage flash, dissolve, and VAT quality LOD changes reach them together with the body. Animated bounds grow to enclose them.

VatAnimator field reference

The component the baker's prefab ships with. Most of it can be left alone, but two fields decide whether your agents look like they are walking or moonwalking, so read the Locomotion group at least once.

References

Field What it controls
Renderer The renderer showing the VAT mesh. Left empty, it takes the first child renderer
Mesh Filter Optional. Used to assign the VAT mesh on spawn
Vat Asset The baked asset holding the idle, walk, run and optional attack clips
Shared Vat Material Optional material override applied on spawn. It has to use the package VAT shader. Use it to share one material across prefabs that were baked separately

Visibility

Field What it controls
Update Only When Visible On by default. Skips playback writes while the renderer is off camera
Visibility Grace Time Seconds of continued updating after the renderer leaves the screen, default 0.15, so agents at the frame edge do not pop

Timing

Field What it controls
Use Unscaled Time Off by default, so Time.timeScale drives playback and a slow motion or hit stop effect reaches the animation, the way it would an Animator. Turn it on to keep agents animating at full speed while the game is paused

Flip it from code with the UseUnscaledTime property rather than by writing the serialized field, since the property re-anchors the playback clock. Switching directly leaves the agent's timestamps on the clock it just left.

Locomotion

Field What it controls
Speed Smoothing Time Smooths the speed that drives the walk and run blend, the playback rate and the idle transition. Default 0.15 seconds. A crowded agent's raw velocity is pushed around by personal space, body blocking and depenetration, and those single-frame spikes snap the pose between walk and run. Higher reads steadier and reacts more slowly. 0 drives the animation from raw velocity
Set Match Speeds By Hand On: the two match speeds below are used exactly as typed. Off: they come from the VAT asset, which measured how fast the walk and run clips cover ground in the bake, times this object's scale, and a clip the bake could not measure falls back to the typed value here. Default On, so a prefab saved before this field existed keeps the speeds it already had typed. A prefab the VAT Baker creates now starts Off
Walk Match Speed The planar speed at which the walk clip is a perfect match, used as typed while Set Match Speeds By Hand is on. Default 1.25. Off, and the VAT asset has a measured walk speed, the field is greyed out and shows that speed at this object's scale instead; with no measured speed yet it stays editable as the fallback
Run Match Speed Same as Walk Match Speed, for the run clip. Default 3.5
Idle Speed Threshold Below this speed a moving agent blends back to idle. Default 0.02. While Idle Blend Duration is 0 it no longer decides that: the agent goes idle as soon as it is at or under Idle Exit Speed Threshold, and this value only sets how low that threshold can go
Idle Exit Speed Threshold Above this speed an idle agent blends into locomotion. Default 0.1. Keep it above the threshold above or agents flicker between the two near zero
Idle Commit Time How long an agent has to stay under Idle Speed Threshold before it commits to idle. Default 0.4 seconds. Only this direction waits, because a body held still by a crowd keeps trying to walk and chatters between the two. Starting to walk is still instant. Not used while Idle Blend Duration is 0, and the inspector greys it out
Idle Blend Duration Crossfade in and out of idle, default 0.12 seconds. The shader only pays for the extra blend sample during the transition. At 0 there is no crossfade: the pose switches at Idle Exit Speed Threshold in both directions, without waiting for Idle Commit Time
Playback Speed Scale A blanket multiplier on the computed playback speed. Default 1. Reach for it last
Min Moving Playback Speed A floor so a very slow agent still animates instead of looking frozen. Default 0.35
Reset To Idle On Spawn Writes idle state when a pooled agent is reused, so it does not inherit the previous occupant's pose. On by default
Randomize Phase On Spawn Offsets each agent's playback phase so a crowd does not march in lockstep. On by default, and worth leaving on

Moonwalking, or running in place

Both symptoms come from the same mismatch. Walk Match Speed and Run Match Speed describe how fast the source clips were authored to move, and the component compares them against how fast the agent is actually travelling. They do not set how fast anything moves. If your Movement Profile's Max Speed is 7 and Run Match Speed here is 3.5, agents outrun their own animation and slide. A prefab the VAT Baker creates takes both speeds from the bake. A prefab saved before 1.1 still plays the speeds typed on it, so turn Set Match Speeds By Hand off there to take the measured ones. Then tune Max Speed for the feel you want.

The Swarm Agent Archetype inspector adds up what this means for a whole archetype: under Movement Profile it says how the walk and run blend plays across that profile's Max Speed range, warns when the slowest agents are too slow for the walk clip, which is never played under Min Moving Playback Speed, and notes when the run plays well above the speed it was animated at. See Swarm Agent Archetype.

Playback

Field What it controls
Playback Control Who advances this instance each frame. Automatic hands it to the built-in driver, which creates itself and needs no setup. Manual means your own code calls SyncVelocityParameters once a frame instead. Default Automatic
Speed Source Where the driver reads this instance's speed from. Transform Movement measures how far the object moved this frame, so anything that moves the transform drives the blend. Fixed Speed ignores movement and plays at one speed forever, which is what something animating on the spot wants. Default Transform Movement
Fixed Speed Speed in units per second reported to playback while Speed Source is Fixed Speed. Default 1.25. Compare it against Walk Match Speed and Run Match Speed to see which clip it lands on

Swarm agents are set to Manual, and that is deliberate

Massive Swarm System puts every agent it spawns on Manual. Its visual manager already syncs them on its own refresh cadence, pushes a per-agent quality tier, and feeds SIMULATED velocity rather than the rendered transform delta, which carries interpolation and render smoothing on top of it. Letting the shared driver play them as well would undo all three.

A prefab you drop in a scene by hand keeps Automatic and plays on its own. The driver is a singleton that creates itself when the first instance needs it, so there is nothing to add to the scene, and VatPlaybackDriver.Instance.DrivenCount says how many instances it is playing.

Attack

Field What it controls
Attack Blend In Duration Crossfade from locomotion into the attack clip, default 0.1 seconds
Attack Blend Out Duration Crossfade back when the attack ends, default 0.1 seconds
Fit Attack Clip To Attack Rate Speeds the attack clip up when the agent attacks faster than the clip can play, so every attack finishes before the next one starts. On by default. Without it a fast attack rate cuts each attack short and restarts it, and the agent never reaches the part of the animation that lands the hit. It only ever speeds up, never slows a short clip down to fill a long gap, and never past 4x. An attack timed to its Hit Time, such as a swarm swing, sets its own speed and ignores this

The first two do nothing unless the assigned VAT asset actually has an attack clip baked into it.

Driving it from code

Member What it does
SyncVelocityParameters(Vector3 velocity) Advances one instance. Call it once a frame for anything on Manual. Two longer overloads take an explicit time pair, and a visibility flag, for a driver that has already resolved both
PushShaderClock(float time, float unscaledTime) Static. Advances the global clock every VAT shader reads
SetMatchSpeedsByHand Property. true plays the two match speeds as typed. false takes them from the VAT asset, scaled by this object, and falls back to the typed value for a clip the bake could not measure. Setting it also calls RefreshMatchSpeeds()
RefreshMatchSpeeds() Works the match speeds out again. The instance resolves them when it is set up and when it spawns; call this yourself after changing the object's scale or the VAT asset's clip speeds while the instance is already in use
TryGetLocomotionPlayback(float planarSpeed, out float runWeight, out float walkPlaybackSpeed, out float runPlaybackSpeed) What playback would do at a given speed: how much of the pose is the run, 0 to 1, and how fast each clip plays, 1 being its baked speed. false when there is no VAT asset, or it has no walk or run clip
TryPlayAttack(float playbackSpeedScale = 1f, float availableSeconds = 0f) Starts the baked attack clip. false when the asset has no attack clip
TryPlayAttackTimedToHit(float hitAtSeconds) Starts the attack clip at whatever speed lands its Hit Time hitAtSeconds from now, held to MinAttackHitSyncSpeed (0.5) to MaxAttackHitSyncSpeed (4). With no Hit Time, or hitAtSeconds of 0, the clip plays at its baked speed
GetAttackHitSyncSpeed(VatAsset asset, float hitAtSeconds) Static. The speed the call above would need, before the clamp, so an editor can say when it will not fit. 0 when the asset cannot be timed
ReleaseAttackToLocomotion() Lets the playing attack end as soon as the instance moves, blending into the walk instead of sliding. Call it when your code stops holding the attacker in place. An instance that stays put plays the clip out
IsAttackPlaying Poll this rather than waiting for a callback. There is no event on purpose: at a thousand agents, delegate allocation costs more than a few float reads
StopAttack() Ends it early, which is the only way out of a looping attack clip
TryPlayDeath(out float clipSeconds) Plays the baked death clip once and holds its last frame until the instance is spawned again. clipSeconds is how long it takes to reach that frame, so you can start your own fade after it. false when the asset has no death clip. It needs no further calls: one write carries the clip to its end
IsDying True from TryPlayDeath until the instance is spawned again. TryPlayAttack refuses while it is
UseUnscaledTime Flip the timing mode through the property rather than the serialized field, since the property re-anchors the playback clock

Nothing animates until the clock lands

PushShaderClock has to be called once a frame whether or not any instance changed state, because the shader resolves every instance's frame against it. The built-in driver and the swarm's visual manager both call it, so ordinary setups never touch it. Drive instances yourself on Manual with neither of those in the scene and you get correct state on a permanently frozen mesh, with no error and no warning. Calling it more than once in a frame is free: every call after the first is an int compare.

availableSeconds on TryPlayAttack is how long the caller has before it asks for the next attack. Pass 0 and the clip plays at its baked speed. The swarm's contact damage passes its Contact Hit Interval, which is what lets Fit Attack Clip To Attack Rate keep a clip from being cut off when contact ticks faster than the clip. A swing uses TryPlayAttackTimedToHit instead.

Previewing in the inspector

The component's inspector has a preview toolbar: Idle, Walk, Run, Attack, Death and Stop. It plays the baked clips in the Scene view without entering Play mode, which is the fastest way to confirm a bake came out right. Attack and Death are greyed out, with a tooltip saying why, when the VAT asset has no such clip. Death holds the last frame; any other button stands the character back up.

The Preview Speed slider is the useful part. It runs the same idle threshold and walk-to-run blending the runtime uses, so dragging it up from zero shows you exactly where your agents will switch gait and whether the transition looks right at the speeds your Movement Profile actually produces. Auto Refresh keeps the preview animating in edit mode; it switches itself on when you press a button and off when you press Stop.

The whole section is replaced by a hint until both a renderer and a VAT asset are assigned.

VAT visibility LOD

When Enable VAT Quality LOD is on in SwarmSettings, each agent's VAT shader quality follows whether the agent is being drawn at all, not its simulation importance tier. An agent on screen renders at full quality no matter how far it is from its target, and so does one that has left the frustum but still casts a visible shadow, because its silhouette has to stay right. An agent that is drawn nowhere renders at cheap quality: frame interpolation is disabled and all shaders snap to the dominant walk/run clip. For the normal-texture: Standard and High keep the per-vertex baked normal off screen so agents stay correctly shaded when they return to view; Mobile drops the normal tap off screen. Nothing is drawing those agents, so the setting changes neither the look nor the GPU cost; GPU cost comes from the render tier. The per-pixel normal-map detail (surface Normal Map texture) is not visibility-gated. It is always on or off based on the material keyword, regardless of LOD state.

See VAT Render Quality Tiers for the full breakdown.

Animator-Based Animation (SwarmAgentAnimation)

For agents that need Animator blend trees, transition logic, or per-parameter animation control, add SwarmAgentAnimation to the prefab. It writes speed float parameters to the Animator based on the agent's simulated velocity, and it can set a trigger when the agent attacks.

SwarmAgentAnimation is visibility-aware: when the agent's renderer has been off screen past the grace period, it skips Animator.SetFloat calls entirely. That saves the parameter writes and nothing more. What stops an off-screen Animator from evaluating its skeleton is the Animator Culling Mode below, and an on-screen Animator evaluates every frame whatever this component writes.

Key fields:

Field What it does
Speed Smoothing Time Smooths the velocity that drives the Animator speed parameters. Default 0.15 seconds. Feeding a crowded agent's raw velocity into a blend tree snaps it between walk and run poses, because personal space, body blocking and depenetration push that velocity around frame to frame. 0 writes the raw value. It matches Speed Smoothing Time on VAT Animator, so both animation paths behave the same.
Forward Speed Float Animator float that receives forward/backward speed. Leave empty to disable.
Strafe Speed Float Animator float that receives left/right speed. Leave empty to disable.
Attack Trigger Animator trigger set when the Attack Profile plays an attack. Disabled by default, which leaves the Animator alone during attacks. See Attack animation on an Animator agent.
Use Planar Speed When Strafe Parameter Missing When no strafe float is configured, writes total planar speed into Forward Speed so 1D blend trees still animate while agents sidestep.
Apply Animator Culling Mode When on, sets the Animator's culling mode to the value below each time an agent is spawned.
Animator Culling Mode The culling mode applied to the Animator on spawn. Cull Completely stops Animator evaluation entirely when the agent is off screen, which is the cheapest option for large crowds.
Update Only When Visible Skips parameter writes when the agent's renderer is off screen.
Visibility Grace Time Keeps updating briefly after leaving the camera view to prevent pop at the screen edge.
Animator The Animator to write to. Left empty, it takes the first Animator on this object or its children.
Visibility Renderer The renderer used to decide whether the agent is on screen. Left empty, it takes the first SkinnedMeshRenderer, or failing that the first Renderer. Set it by hand when the agent's largest renderer is not the one you want driving visibility.
Disable Root Motion On by default. Turns the Animator's root motion off so the swarm simulation keeps control of where agents actually go. Leave it on unless you know why you want it off, because root motion fighting the simulation is a hard problem to diagnose.
Speed Parameter Scale Multiplies both speed values before they reach the Animator. Default 1. Use it when your blend tree was authored against a different speed range than your Movement Profile produces, instead of re-authoring the tree.
Min Parameter Change How much a speed has to move before a new value is written, default 0.01. This is a real saving at high counts: it skips SetFloat calls for agents whose speed is barely changing. 0 writes on every visible sync.
Reset Parameters On Spawn On by default. Zeroes the speed floats when a pooled agent is reused, so a fresh agent does not inherit the previous occupant's running pose.

Attack animation on an Animator agent

An Animator agent plays its attack through a trigger parameter. Until you set one it keeps playing locomotion while it attacks.

  1. In the Animator Controller, add a Trigger parameter, for example Attack. Add a transition from your locomotion state into the attack state with that trigger as its condition and Has Exit Time off, and a transition back with Has Exit Time on.
  2. On the prefab, open SwarmAgentAnimation and pick the parameter in Quick Setup → Attack Trigger. The dropdown lists the controller's triggers.
  3. On the Attack Profile, Swing Play Animation sets the trigger when a swing starts. It is on by default. Contact Play Animation sets it on each contact hit and is off by default.

The archetype inspector tells you when a profile plays an attack animation and the prefab's Attack Trigger is still empty.

Damage does not move. It lands on the Attack Profile's timers whether or not the trigger is set. An Animator clip has no Hit Time for the swing to aim at, so the blow shows wherever the clip puts it: set Swing Windup to the time your clip takes to reach its impact frame.

What the component does with the trigger:

  • An off-screen agent skips it, as a VAT agent skips its clip. Damage still applies.
  • A trigger the controller has not consumed is taken back, so an attack never plays late. For a swing that happens when recovery ends. For contact hits it happens one Contact Hit Interval after the hit that set it. It also happens when the agent leaves the screen and when its pooled visual is reused.
  • Whether a trigger that arrives mid-clip restarts the clip is up to your controller. With no transition from the attack state to itself, the clip finishes first, and with a contact interval shorter than the clip the attacks play back to back.
  • A name that is not a trigger on the controller logs one warning and is skipped.

Animation events

Events on your attack clip work as they do in any Unity project. Unity calls the named method on a component that sits on the same GameObject as the Animator, so that is where your own script goes, for an impact sound or a particle burst on the frame the blow lands. Damage does not wait for the event and does not need one.

public class AttackImpactFx : MonoBehaviour
{
    [SerializeField] private AudioSource m_audio;

    // Animation event on the attack clip's impact frame, Function: OnAttackImpact
    public void OnAttackImpact() => m_audio.Play();
}

Culling mode: by default, SwarmAgentAnimation applies AnimatorCullingMode.CullCompletely to every spawned agent. This is the cheapest culling mode: the Animator stops evaluating entirely when off screen. Change Animator Culling Mode in the component if you need a different mode.

Camera-keyed animation refresh

SwarmVisualManager keys animation refresh cadence on the camera, not the simulation importance tier. An on-screen agent close to the camera refreshes every visual sync for smooth animation. An on-screen agent farther than Distant Visible Distance from the camera refreshes on the Distant Visible Animation Refresh stride.

An agent stops refreshing once Visibility Grace Time runs out, provided Update Only When Visible is on. Visible here means Unity still has to draw the agent, and that includes drawing only its shadow while the body sits just outside the camera view. Under a directional light, a shadow crossing the ground belongs to a body that is still animating. Nothing is lost by not refreshing an agent that is drawn nowhere: VAT playback advances on elapsed time rather than on frame count, so a returning agent resumes at the pose it would have reached, and SwarmAgentAnimation agents are already halted by Cull Completely. Uncheck Update Only When Visible and the agent falls back to the Off-Screen Animation Refresh stride instead.

Higher stride values reduce Animator.SetFloat calls (for SwarmAgentAnimation agents) and MaterialPropertyBlock writes (for VAT agents). These settings live under Visibility LOD in SwarmSettings.

Keyed on distance to the camera, not on the Importance LOD tier. Is Unity drawing it? a shadow on its own counts no refresh stops every 4th sync if you untick the toggle yes Nearer than Distant Visible Distance (30)? yes every visual sync no every 2nd sync Strides come from Distant Visible Animation Refresh and Off-Screen Animation Refresh.
Two questions, three cadences. Worth holding next to the Importance LOD matrix, because they look alike and measure different things: this one asks how far the agent is from the camera, while the importance tier asks how far it is from its target. An agent can be simulated cheaply and still animate every frame, or the other way round.

SwarmVisualManager

SwarmVisualManager owns the agent visual layer. It maintains a pool of visual GameObjects per prefab and updates them every frame from simulation state. Every frame it reads from SwarmManager and updates transforms, Animator parameters, and VAT playback data. Visuals follow the simulation, never the other way around.

SwarmManager creates and wires SwarmVisualManager automatically when you add a manager via GameObject → Massive Swarm System → Swarm Manager (or the Scene View overlay). You only need to add or configure it by hand when building a custom setup.

Inspector fields

Field What it controls
Manager The SwarmManager that owns the simulation data. Auto-assigned when both components share a GameObject.
Fallback Agent Prefab Prefab used when a spawn request or archetype supplies no prefab. Assign the built-in MSS Default Agent here for quick testing before your own art is ready.
Agent Root Parent transform for pooled agent instances. Defaults to this GameObject when left empty.
Initial Pool Size Per-prefab warm-up count. Pre-allocates this many instances when the first agent of that prefab spawns to reduce spawn spikes. This is not the simulation cap; total live agents are bounded by SwarmSettings → Max Agents, and pools grow past this value on demand.

Mobile prefab checklist

Apply these before releasing on mobile

  • Use VAT animation instead of SkinnedMeshRenderer + Animator.
  • Use a single material per agent (no multi-material mesh).
  • Keep the mesh low-poly.
  • Disable shadow casting on the agent renderer.
  • Set Animator Culling Mode to Cull Completely if using SwarmAgentAnimation.