Script Reference
Two separate surfaces, and the difference matters:
| Namespace | Assembly | Ships in a build | |
|---|---|---|---|
| Editor API | AnimationWorkbench.Editor | AnimationWorkbench.Editor | No |
| Runtime API | AnimationWorkbench | AnimationWorkbench.Runtime | Yes |
Editor code only compiles inside an Editor folder or behind #if UNITY_EDITOR. Everything your game calls at runtime lives in the runtime assembly - see Audio Integration for how to reference it from your own assembly definition.
Editor API
Open the main window
using AnimationWorkbench.Editor;
AWContextMenuExtensions.ShowAnimationWorkbenchWindow();
Query the animation library
AWAnimationLibrary is the index the browser is built on. Items carry their metadata without loading the clip, so filtering thousands of them is cheap:
var lib = AWAnimationLibrary.Instance;
// Metadata only - no clips loaded
var longLoops = lib.AllAnimations
.Where(a => a.isLooping && a.duration > 2f);
// The clip itself, when you actually need it
var walkClips = lib.AllAnimations
.Where(a => a.Clip != null && a.Clip.name.Contains("Walk"));
Useful fields on an item: name, path, assetPath, guid, duration, frameCount, frameRate, isLooping, isHumanoid, isLegacy, usageCount, usedInControllers, tag, isFavorite.
Going the other way:
var item = AWAnimationLibrary.FindAnimationItemByClip(clip);
:::tip Prefer the metadata fields over Clip
duration, isLooping and friends are already in memory. Touching .Clip loads the asset. Over a large library that is the difference between instant and noticeable.
:::
Open a clip in the Keyframe Editor
AWKeyframeEditorWindow.OpenWithClip(clip, createNewWindow: true);
createNewWindow: false reuses an existing editor instead of opening another one.
Characters
var db = AWAnimationCharacterDatabase.Instance;
Thumbnail cache
AWThumbnailController.Instance.ClearAllCaches();
Clears RAM, GPU and disk caches. They rebuild on demand - this costs render time, not data.
Check the edition
bool isPro = AWSettings.IsPro;
See Lite & Pro.
Runtime API
Two things live out here. The audio pipeline, fully documented on the Audio Integration page - what follows is the short form - and IAWPlayheadDriven, the hook a game component implements so that Pose Edit can drive a prop's moving part.
Play a sound
using AnimationWorkbench;
AWSFXManager.Instance.Play("UI_Confirm"); // 2D
AWSFXManager.Instance.Play("Impact_Wood", hit.point); // 3D
AWSFXManager.Instance.PlayMusic("Ambient_Cave");
Channels
AWSFXManager.Instance.SetChannelVolume(footsteps, 0.4f);
AWSFXManager.Instance.SetChannelMuted(dialogue, true);
AWSFXManager.Instance.GlobalMuted = true; // SFX only, music unaffected
Per-character playback
var receiver = GetComponent<AWAudioEventReceiver>();
receiver.Play("Footstep_Mud"); // honours this character's mute and channel override
Validate cue keys
var db = AWSFXManager.Instance.audioDatabase;
if (!db.Contains("Footstep_Mud"))
Debug.LogWarning("Cue missing - re-bake the audio database.");
Custom playback rules
public sealed class UnderwaterGate : IAWAudioGate
{
public bool Evaluate(ref AWAudioPlayContext ctx)
{
ctx.Volume *= 0.3f;
return true; // false would veto the sound
}
}
AWSFXManager.Instance.AddGate(new UnderwaterGate());
Drive a prop's moving part
Some props have a moving part of their own: a bow's string, a crossbow's lever, the slide of a pump action. It is not animated by the clip - the string belongs to the weapon, the draw belongs to the character - so while you pose the draw, the string hangs slack.
Implement IAWPlayheadDriven on a component in the prop's prefab and Pose Edit hands it the playhead, once per sample:
using AnimationWorkbench;
using UnityEngine;
public class BowString : MonoBehaviour, IAWPlayheadDriven
{
[SerializeField] private Transform nock;
[SerializeField] private Vector3 drawnOffset = new(0f, 0f, -0.35f);
private bool _restTaken;
private Vector3 _rest;
/// What the game calls with whatever it already knows about the draw.
public void SetDraw(float draw)
{
CaptureRest();
nock.localPosition = _rest + drawnOffset * Mathf.Clamp01(draw);
}
/// 0 at the clip's first frame, 1 at its last - the same number.
void IAWPlayheadDriven.SetPlayheadTime(float normalizedTime) => SetDraw(normalizedTime);
private void CaptureRest()
{
if (_restTaken) return;
_rest = nock.localPosition;
_restTaken = true;
}
}
The component ships with your game and needs nothing else: IAWPlayheadDriven lives in the runtime assembly precisely so that implementing it does not drag an editor reference into your build.
:::caution Take your rest pose lazily, not in Awake
The prop is instantiated into an editor stage, where Awake and Start never run - the tool calls your method directly. A rest pose read in Awake is therefore all zeroes in Pose Edit, and the part jumps to a place nobody authored. Capture it on first use, as above, and the same code serves both sides.
:::
A few properties of this hook, in one place:
| What arrives | The playhead, normalised: 0 at the clip's first frame, 1 at its last. Normalised rather than in seconds so a part keeps its meaning when the clip is retimed |
| When | At the end of every sample - scrubbing, playback, frame stepping. Paused playback means no sample, and the part stands still: that is the intended pause |
| Where it is switched on | The timeline chip on the prop's row in the Pose Edit HUD. The chip only appears if the prefab carries a driven component; following is off until asked for |
| Not following | Your method is called with 0, not skipped, so the part goes back to rest instead of freezing half-drawn |
| Never a curve | Writing transforms inside the prop registers nothing with the recorder. A driven part cannot be picked, cannot be keyed and can never end up in the clip |
Give the prop no Animator of its own for this - a prop's Animator is stripped on the way into the stage anyway, because a second piece of motion laid over the pose is what a prop must never bring.
Bend a bow in your game
A bow can only be drawn because its limbs give way. The string does not stretch, so a game that moves the string's bone and nothing else does not draw a bow - it stretches a cord. AWBowDraw supplies the missing half: move the pull bone from your own code, and the limbs bend, the tips travel, and the string keeps its length.
Add it from Add Component, under Animation Workbench, Bow Draw, and assign five transforms:
| Field | The bone |
|---|---|
| Pull | The one the string hangs on - the one your game moves. Everything else follows from where it stands |
| Upper Grip / Lower Grip | Each limb's root, at the grip: the end that holds still |
| Upper Tip / Lower Tip | Each limb's tip, at the nock, where the string hangs |
Everything else is measured off the rig the first time it runs - limb lengths, string length, rest angles. There is nothing to calibrate by hand.
Weight painting cannot stand in for this. Skinning is a linear blend, so a bone that moves can only ever produce movement, never a bend. On the test bow the nock travels 0.054 back and 0.053 inward at a draw of 0.30; painting gets you the first number and never the second, and the inward half is what a drawn bow looks like.
Readable while it runs:
Stretch | How far the string would have to stretch, as a share of its length. 0 while the bow can still give; above that you are pulling further than this bow goes |
IsCalibrated | Whether the rest measurements have been taken |
UpperDegrees / LowerDegrees | How far each limb is bent right now |
:::note It runs in play mode only
There is no [ExecuteAlways] on it. The component writes bone rotations every frame, and doing that in an open scene would mark the scene dirty without being asked. To try a draw while rigging, use the Draw slider in Rig Edit.
:::
The component and its solver use nothing else from Animation Workbench - no database, no settings, nothing from the editor - and compile against UnityEngine alone. Delete the rest of the package and your bow keeps working. That is deliberate: the tool is for authoring, and what it produces has to run without it.