Skip to main content
Flow Core Documentation
Menu

Extension

Authoring Custom Instructions

Add a supported typed operation that designers can run inside an Action.

Audience
Unity developers
Time
25 minutes
Requires
C#, Flow Core runtime assembly access, and codegen access
Modules
Flow Core, C#
On this page

Create a custom Instruction when Flow Core should perform a project-specific operation inside an Action list. Keep the runtime contract typed, explicit, and free of editor dependencies.

Define runtime data and behavior

The Instruction below resolves a typed string and logs it:

using System;
using System.Threading.Tasks;
using UnityEngine;
using TwoCatsCode.FlowCore;

[FlowInstruction("Log Project Message", "Project", "Log a typed string value.")]
public sealed class InstructionLogProjectMessage : IInstruction
{
    [Serializable]
    public sealed class Data : InstructionData
    {
        public FlowValueGetStringData Message = new();

        public override InstructionData Clone()
        {
            return new Data
            {
                Message = Message?.Clone() as FlowValueGetStringData
                    ?? new FlowValueGetStringData()
            };
        }

        public override string Summary(FlowContext context)
        {
            return $"Message: {Message?.Summary(context)}";
        }
    }

    private readonly Data data;

    public InstructionLogProjectMessage(Data data)
    {
        this.data = data ?? new Data();
        this.data.Message ??= new FlowValueGetStringData();
    }

    public ValueTask<InstructionResult> ExecuteAsync(FlowContext context)
    {
        if (FlowValueResolveHelper.TryResolveValue(
                data.Message, context, out string value, out _))
        {
            Debug.Log(value);
        }

        return new ValueTask<InstructionResult>(InstructionResult.Continue);
    }

    public string Summary(FlowContext context) => string.Empty;
}

Preserve the contract

  • Put the type in a runtime assembly.
  • Keep serialized fields inside Data.
  • Deep-clone nested Flow value data.
  • Resolve typed values through the supplied FlowContext.
  • Return an intentional InstructionResult.
  • Keep editor UI code out of runtime assemblies.
  • Avoid allocations and reflection in hot paths.

Register and verify

  1. Run the Flow Core code-generation and registry workflow used by the project.
  2. Wait for Unity to recompile.
  3. Add an Action to a test graph.
  4. Search for Project > Log Project Message in the Instruction picker.
  5. Bind a literal and a Blackboard-backed string in separate tests.
  6. Enter Play Mode and confirm both resolve.
Image 05_02_01Screenshot production note

此处插图应该是 Action Instruction Picker 中 Project > Log Project Message 的截图;同时展示添加后的 typed Message 字段与 Summary,并框选自定义分类和运行结果。

Common Mistakes

  • Registering the runtime type but not refreshing editor and runtime registries.
  • Returning shared nested Data from Clone.
  • Storing per-execution state on the shared graph asset or Instruction data.
  • Adding UnityEditor references to the runtime assembly.
  • Swallowing a failed value resolution while implying the operation succeeded.
  • Using reflection in a frequently executed Instruction.

What You Built

You added a typed runtime operation that designers can place inside any Action, configure with literals or Blackboard values, serialize with a graph, and execute without editor-only dependencies.