Subject Presets
A subject preset produces a track's subject on the client when the sequence plays, for subjects that don't exist while you author: the local player's character, their equipped weapon, their pet. Flow's own character presets are built on the same API described here.
The shape of a preset
A preset is a ModuleScript that returns a PresetDefinition:
| Field | Meaning |
|---|---|
Name | Unique, identifier-like. Custom is reserved |
DisplayName | What the editor shows in the Kind dropdown |
Description | Shown in the Inspector |
SubjectClass | The class of the subject it produces, such as "Model" |
Resolve(context) | Runs on the client before the sequence's clock starts, and may yield. Returns { Subject = instance, Cleanup = function }, or nil |
CreateStandIn(context) | Returns an unparented placeholder for the editor to author against |
context carries the sequence, the binding being resolved, the playback's root, and a label for warnings.
See PresetContext.
Example
This preset plays a sequence against a copy of whichever sword the local player has equipped:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Swords = ReplicatedStorage:WaitForChild("Swords")
return {
Name = "EquippedSword",
DisplayName = "Equipped Sword",
Description = "A copy of the local player's equipped sword.",
SubjectClass = "Model",
Resolve = function(_context)
local swordName = Players.LocalPlayer:GetAttribute("EquippedSword")
local template = swordName and Swords:FindFirstChild(swordName)
if not template then
return nil -- falls back to the stand-in
end
local sword = template:Clone()
return {
Subject = sword,
Cleanup = function()
sword:Destroy()
end,
}
end,
CreateStandIn = function(_context)
return Swords.Default:Clone()
end,
}
Flow places both the subject and the stand-in for you: it pivots them to the position authored on the
binding and parents them where they will render, so Resolve only has to build the subject.
What Flow handles
- Timing. Every preset in a sequence resolves before its first frame. A slow
Resolvedelays the start of a local playback; a synced playback joins at the right elapsed time once its presets are ready. - Failure. If
Resolveerrors or returns nil, the stand-in is used in its place, so a sequence never loses a subject to a network hiccup. - Cleanup.
Cleanupruns when the playback ends. Leave it out for a subject your preset doesn't own. - Containers. A preset binding is a container. Tracks bound to instances inside the stand-in, such as the sword's blade, resolve to the instance at the same path inside the real subject at play time.
Installing a preset
Import it the same way as a section type: the Inspector's
Custom Section Types import accepts preset modules too, and installs them under
ReplicatedStorage.Flow.CustomPresets. You can also place the module there by hand. Custom presets can't
replace the built-in ones.
A sequence that uses a preset the place doesn't have warns in the editor, and in game those tracks are skipped like any other subject that can't be found.