Skip to main content

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:

FieldMeaning
NameUnique, identifier-like. Custom is reserved
DisplayNameWhat the editor shows in the Kind dropdown
DescriptionShown in the Inspector
SubjectClassThe 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 Resolve delays the start of a local playback; a synced playback joins at the right elapsed time once its presets are ready.
  • Failure. If Resolve errors or returns nil, the stand-in is used in its place, so a sequence never loses a subject to a network hiccup.
  • Cleanup. Cleanup runs 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.