A State Preset stores selected public property values for one state-enabled owner type. Use one when a named gameplay condition should temporarily change Inspector values, such as Jump force, movement speed, camera field of view, or an item setting, then restore the normal values when that condition ends.

When a preset is appropriate

Use a State Preset for value changes that already have a gameplay owner and a clear on/off condition. The system applies the preset while its State is active; it does not detect the condition, start an ability, play an animation, or save gameplay progress.

Keep the normal value directly on the component, ability, movement type, view type, or other state-enabled object. Put only the properties that should differ into the preset. An unlisted property continues to use its normal value or a value supplied by another active State.

Use separate gameplay logic when the change needs a sequence, spawned object, collision query, or another action rather than a property override.

Create and assign a preset

  1. Select the component or nested UCC object that owns the value and configure its normal Inspector values first. These become its runtime Default values.
  2. Expand States at the bottom of the owner Inspector. The table contains State, Preset, Blocked By, Persist, and Activate columns, with the fixed Default row at the bottom.
  3. Select the plus button and choose Create New Preset.
  4. In Save Preset, save a unique .asset under a project-owned folder such as Assets/<ProjectName>/Presets. A new asset is typed for this owner and begins with no stored properties; it is not a snapshot of every current value.
  5. Confirm the new row references that asset in Preset, then give the row a unique, case-sensitive State name that matches the condition that will activate it.
  6. Select the preset asset. In its Inspector, choose a property from Add Property…, then enter the value that should apply while this State is active.
  7. Return to the owner and drag the row to its priority position. Keep Default last; it cannot be edited, removed, or moved.
  8. Save the owner scene or prefab and the preset asset.

States add menu with Create New Preset for the selected state-enabled owner

Add Existing Preset opens a preset asset picker and adds a State that references the selected asset. Use an asset created for the same concrete owner type. The State Inspector rejects an incompatible recorded type rather than applying similarly named properties to the wrong object.

Add, update, and remove properties

The preset Inspector lists public properties available on its recorded owner type. A property needs a usable public getter and setter to be a safe runtime override. The released Inspector can list a getter-only property, but the runtime delegate has no setter to apply it; do not add read-only properties.

Jump preset Inspector with Add Property options for public Jump properties

When a property is first added, the preset uses the type’s default value from a temporary default instance. It does not read the selected scene or prefab owner. Choose one of these workflows:

  • Enter the state-specific value directly in the preset asset.
  • Configure the desired value on the owner, then select the row’s Persist control to copy the owner’s current value into properties already stored by that preset.

Persist updates only properties already present in the preset. It changes the shared asset, not just that row or instance. It does not copy a top-level UnityEngine.Object property in released Version 3; assign an allowed project asset reference directly in the preset Inspector instead.

Select the X beside a property to remove that complete property and its stored value. The State will stop overriding it the next time values are initialized and applied.

Preset property row with the X removal control outlined in red

Choose what owns each value

Goal Recommended setup
One temporary difference Leave the normal value directly on the owner and store only that property in one preset.
Several independent changes Use separate presets and State names when the conditions start and stop independently. Each preset should contain only the values that condition owns.
One condition changes several related values Put those properties in one preset so they activate and restore together.
Several objects use identical tuning Share one preset asset only among the same owner type. Runtime initialization creates per-owner delegate instances, while the serialized values remain shared.
One character or item needs different tuning Duplicate the preset asset and assign the copy before editing it. Editing a shared asset changes every row that references it.
A higher-priority State changes the same property Move the State nearer the top of States. Active States are recombined so the top row supplies the final overlapping value.
One State should suppress another completely On the row that should be suppressed, add the stronger State to Blocked By. A blocked State remains recorded as active but its preset is skipped.
A quick Play Mode value check Use the row’s Activate control in Play Mode. It toggles that row directly; still test the real ability, item, trigger, or code path afterward.

The generated Default preset is different from the .asset assigned to a named State. During initialization, it captures the owner’s normal public values. When a named State deactivates, Default restores the properties that State changed, then the remaining active, unblocked States are reapplied from lower priority to higher priority.

Directly editing an affected runtime property while its State remains active is temporary. The next State activation, deactivation, block change, or recombination can apply the preset again. Change the preset or the condition’s ownership instead of fighting an active override.

Work with nested values, lists, and references

A top-level public property can contain a serializable class, struct, array, or list. The preset Inspector expands its nested data, and the State treats that top-level property as one override. Removing it removes the complete nested value.

  • Use a nested property when the complete setting should change and restore together.
  • Expose separate top-level public properties when different States need independent priority over individual parts.
  • Keep lists and arrays initialized. The runtime copies their elements into the owner’s existing collection and resizes an array through its setter when necessary; a null destination cannot be updated safely.
  • Store project asset references only when Unity can serialize them in the preset asset. A project-level preset cannot hold a durable reference to a scene object.
  • Do not use a preset as mutable per-instance inventory, target, checkpoint, or save data. Those values belong to their runtime and persistence owners.

How activation and ordering work

  1. A state-enabled owner initializes its State array with State Manager in Play Mode.
  2. The last Default row receives a generated runtime preset that captures the owner’s normal public values and remains active.
  3. Each named preset initializes delegates against that specific owner. When the same asset is already initialized for another owner, the State creates a runtime copy so delegates do not point to the earlier object.
  4. A built-in feature or project call activates a State by its exact name. The preset changes only its stored properties.
  5. When several unblocked States are active, the list is applied from lower priority to higher priority. The row nearest the top is applied last and wins overlapping properties.
  6. Blocked By prevents a row’s values from applying while a named blocker is active and is not itself blocked. Its active flag remains set so it can resume when the blocker ends or is itself blocked. For example, with A blocked by B and B blocked by C, active C suppresses B and can allow active A to apply.
  7. On deactivation, Default restores only the properties affected by that State, then the remaining active States are applied again.

The State Inspector’s Activate control calls the narrow row activation path. It does not represent the owner callbacks or optional global state-change event used by the normal GameObject-based path, so treat it as a visual preset test rather than full gameplay verification.

Editor checkpoint

Before Play Mode, confirm that:

  • the owner exposes States, its normal direct values are correct, and Default remains last;
  • every named row has a unique, case-sensitive name and a preset for the same concrete owner type;
  • each preset contains only public getter-and-setter properties that the State should own;
  • newly added values were entered directly or deliberately captured with Persist;
  • shared assets are meant to remain shared, and instance-specific variants use duplicated assets;
  • nested values and lists are initialized and contain no scene-object reference that an asset cannot serialize;
  • overlapping presets are ordered with the intended winner nearer the top;
  • Blocked By is configured on the row that should be suppressed; and
  • the ability, item, trigger, or project code that owns activation uses the exact same State name.

Verify in Play Mode

  1. Create a small test preset on a visible property, such as Jump Jump Force, camera field of view, or a movement speed value. Record the owner’s normal value.
  2. Enter Play Mode and trigger the real gameplay condition. Confirm the row becomes bold and displays (Active) and the stored property changes to the preset value.
  3. End the condition. Confirm the property returns to the normal value captured by Default.
  4. Add a second State that changes the same property, place it above the first, and activate both. Confirm the top row supplies the final value.
  5. Move that row below the first and repeat. Confirm the winner changes with the list order.
  6. Add the stronger State to the weaker row’s Blocked By field. Activate both and confirm the weaker row is suppressed; deactivate the blocker and confirm the still-active weaker State resumes.
  7. Add a nonoverlapping property to one preset. Confirm both States can remain active and combine their independent values.
  8. If the preset is shared, test two owners of the same type. Confirm both use the asset values without one owner’s runtime delegate targeting the other.
  9. Stop Play Mode, reopen the preset asset and owner, and confirm only editor-authored asset and row changes persisted. Runtime active flags and temporary Inspector values should be gone.

Troubleshooting and released-Version-3 limitations

Symptom Check Fix
A new preset contains no component snapshot This is the released workflow: Create New Preset creates an empty typed asset. Add the intended properties, enter their values, or use Persist after the properties exist.
The row becomes active but no value changes The preset has no property, the wrong property was added, or the State is blocked. Open the asset, add the intended property, inspect Blocked By, and repeat the Play Mode test.
A property appears in Add Property… but fails when activated It has a public getter but no usable public setter. The Inspector’s availability check is less strict than runtime application. Expose a public setter or choose another supported property. Do not add a read-only value.
The preset cannot be assigned Its recorded object type does not match the State owner type. Create or select a preset from the same concrete component, ability, movement type, view type, or nested owner.
Persist saved surprising values The wrong owner or shared asset was selected, or the component was already under another active override. Restore or undo the asset, configure the intended owner in Edit Mode, verify the row, and persist again.
Persist does not update an asset reference Released Version 3 skips a top-level UnityEngine.Object property in the Persist path. Assign a project asset directly in the preset Inspector. Do not use a scene-object reference.
Editing one preset changes several characters or items Their rows reference the same asset. Keep the shared asset for common tuning or duplicate it and assign the copy before editing.
The wrong value wins Two active presets include the same property and their list order is reversed. Move the intended winner nearer the top and retest both States together.
The value returns to an unexpected default The normal owner value was changed after State initialization or loaded after Default captured its runtime snapshot. Establish and load normal values before State initialization, or deliberately reinitialize/restore them through the system that owns load order.
A nested list fails or keeps old elements The owner’s collection is null, its getter/setter is unsuitable, or the preset was not refreshed after the desired list changed. Keep the collection initialized, expose a usable public getter/setter, then edit the preset or use Persist for the stored property.
The row is active but does not show (Active) Another active, unblocked row in Blocked By suppresses it. Remove the unintended blocker or end that condition.
OnStateChange is not received during the Inspector test Activate calls the direct row path, and the manager event is only sent by the GameObject-based path when enabled. Test through StateManager.SetState(GameObject, string, bool) and enable State Manager Send State Change Event when an integration needs it.

Saving and networking

The preset .asset, the owner’s State rows, their names, list order, block lists, and preset references are authored configuration. The active flag, generated Default snapshot, runtime delegate copies, linked-object maps, and timed deactivations are transient.

A save system should store the authoritative gameplay condition or active State names that must survive loading. Restore normal owner data first, wait until its States initialize, then reactivate the required names. Saving only the active flag is insufficient when the system that owns the ability, item, camera, or other condition disagrees after load.

State Presets do not replicate themselves or their active status. State Manager Send State Change Event starts disabled and only exposes the GameObject-based change to a listening integration; it does not perform networking. Let authority choose the change, keep matching preset assets on every peer, and let the installed integration or project code synchronize the State name and active value.

  • State System explains State creation, priority, blocking, and cross-owner activation.
  • Events explains registration for the optional global State change event.
  • Abilities covers common owners and gameplay triggers for named States.
  • Movement Types covers movement settings that can be varied with a State.
  • Character Time shows a practical TimeScale State property.
  • Object Fader is an example of a component whose behavior can be tuned by State values.

Developer reference

The released types are in Opsive.Shared.StateSystem. PersistablePreset stores serialized property data and initializes per-owner delegates. StateBehavior is the component owner and StateObject is the nested serializable owner; both expose States, SetState(string, bool), StateWillChange(), and StateChange().

Use the GameObject path when the same State name should update all registered owners on that object and participate in the optional global event:

using Opsive.Shared.StateSystem;

StateManager.SetState(character, "Zoom", true);

StateManager.SetState(character, "DamageFlash", true);
StateManager.DeactivateStateTimer(character, "DamageFlash", 0.25f);

DeactivateStateTimer schedules only deactivation, so activate the State first. StateManager.SetState(object, State[], string, bool) targets one registered owner. StateManager.ActivateState(State, bool, State[]) toggles a specific row and is the path used by the Inspector’s Activate control. Only the GameObject overload sends the optional global OnStateChange(GameObject, string, bool) event when State Manager Send State Change Event is enabled.

Preset.Initialize, UpdateValue, and ApplyValues operate on runtime delegates; they do not save an edited asset automatically. PersistablePreset.CreatePreset(object) creates an in-memory typed preset with empty property data under the editor workflow’s default visibility. Asset creation and durable changes remain editor/project responsibilities.