Skip to content

Flow Module

Technical Docs / Flow Module
Runtime UniTask StateMachine Graph

UNIVERSAL GRAPH RUNTIME · PROCEDURAL EVERYTHING

Flow

어떤 절차적 표현이든 그래프로.

게임 모드 시퀀스, 텍스쳐 생성, 캐릭터 조립, 이벤트 체인 — 데이터든 로직이든 모든 절차를 노드 그래프로 표현하고 실행하는 범용 런타임입니다. 에디터에서 시각적으로 설계하고, 런타임에서 UniTask 기반 비동기로 실행됩니다.

ASYNC UniTask
GRAPH CONTEXTS 3+
EXECUTION Depth-first
STORAGE ScriptableObject

GameMode Graph

게임 세션의 시퀀스와 상태 전환을 그래프로 정의

GameplayFlowNode
게임 시작
월드 로드
scene
플레이어 스폰
scene
이벤트 대기
종료 조건
게임 종료

각 노드는 async — 이벤트 대기, 딜레이, 조건부 분기 모두 자연스럽게 표현

Texture Graph

텍스쳐 생성 파이프라인을 데이터 그래프로 정의

DataFlowNode
BaseColor
Blend
Noise
출력
BrickPattern

실행 흐름 없이 순수 데이터 변환 — 출력 노드가 평가될 때 필요한 입력을 역방향으로 pull

Character Assembly Graph

캐릭터 빌드 과정을 단계별 그래프로 조립

DataFlowNode
골반 Pivot
하체 조립
상체 + 팔
머리 부착
얼굴 생성
캐릭터 완성

같은 그래프 구조로 다른 조립 순서나 파츠를 교체 — 조립 로직을 코드 변경 없이 에디터에서 수정

FlowAsset

ScriptableObject

그래프 구조를 에셋으로 저장하는 컨테이너. 노드 목록, 실행 링크(ExecutionLink), 값 링크(ValueLink)를 보유합니다.

nodesList<FlowNode>
executionLinksfrom → to (슬롯 포함)
valueLinksfrom.slot → to.slot (타입 매칭)
contextProfile허용 노드 타입 필터
IImmutableFlowSerializable

FlowNode

abstract

그래프 내 하나의 실행 단위. 입/출력 포트를 선언하고, 비동기 진입(EnterAsync)과 실행(RunAsync)을 구현합니다.

EnterAsync(ct)노드 초기화 (딜레이, 준비)
RunAsync(ct)노드 메인 로직 실행
TryValueOut<T>타입 안전 값 출력
GetValueInputPorts입력 포트 정의 목록
INodeIFlowValueNode

FlowSession

Runtime

그래프를 실제로 실행하는 컨텍스트. EntryNode부터 깊이 우선으로 노드를 순회하며 실행 흐름을 관리합니다.

BeginAsync(ct, owner)그래프 실행 시작
End() / Dispose()실행 중단 및 정리
Blackboard노드 간 공유 데이터 저장소
UniTaskCancellationToken

Blackboard & Properties

Runtime Data

세션 내 노드들이 공유하는 데이터 레이어. FlowBlackboard는 int 키 기반 딕셔너리, FlowProperty<T>는 변경 구독이 가능한 Observable 값입니다.

Blackboard.Set<T>(key, val)런타임 데이터 저장
Blackboard.TryGet<T>타입 안전 읽기
Property.Subscribe(cb)값 변경 이벤트 구독
Property.Version변경 추적 카운터
ObservableType-safe
FlowNode abstract
GameplayFlowNode
게임플레이 로직, 실행 흐름 제어. 씬 액세스 가능.
Delay If SpawnPawn WaitForEvent
DataFlowNode
순수 데이터 변환. 부수 효과 없음, 값 계산 전용.
ConstantInt MathAdd If (값 선택) EntrySlotFlowNode
AlwaysAllowedFlowNode
컨텍스트 프로파일 관계없이 모든 그래프에서 허용.
FlowEntryNode FlowExitNode Print (Debug)
GraphContextProfile — 그래프 종류별 허용 노드 제어
GlobalProfile 모든 노드 허용 — 개발·테스트용
GameplayGraphContextProfile GameplayFlowNode + DataFlowNode — 게임플레이 그래프
DataGraphContextProfile DataFlowNode 전용 — 텍스쳐·데이터 변환 그래프
1
값 입력 와이어링

세션 시작 시 각 노드의 입력 포트에 연결된 소스 노드를 연결합니다. 이후 실행 중 소스 노드의 출력값이 자동으로 입력으로 흐릅니다.

2
깊이 우선 실행 (Depth-First)

pendingNodes 스택에서 노드를 꺼내며 EnterAsync → RunAsync 순으로 실행. 실행 후 다음 노드들을 스택에 추가합니다.

3
값 Pull 방식

노드가 입력값을 필요로 할 때 TryGetInputOverrideData<T>로 연결된 소스에서 값을 당겨옵니다. 타입 불일치는 제너릭 캐스팅으로 처리됩니다.

4
CancellationToken 전파

모든 async 호출에 같은 CancellationToken이 전파됩니다. 세션이 End()되거나 오너 오브젝트가 파괴되면 전체 실행이 취소됩니다.

FlowSession 실행 의사코드
var pending = new List<INode> { flow.EntryNode };

while (pending.Count > 0) {
    var node = pending[^1];
    pending.RemoveAt(^1);

    ApplyValueInputs(node);       // 입력 포트 값 세팅
    await node.EnterAsync(ct);    // 진입 (딜레이, 준비)
    await node.RunAsync(ct);      // 실행

    pending.AddRange(            // 다음 노드 추가
        flow.GetNextNodes(node)
    );
}
[FlowNode] 어트리뷰트

에디터 팔레트에 표시될 이름과 카테고리 지정

ValuePortDefinition

슬롯 번호와 값 타입으로 포트 선언

GetInputOverrideOrDefault

연결된 포트값 없으면 직렬화 필드 fallback

async UniTask

딜레이·대기·비동기 작업 자연스럽게 표현

[FlowNode("Delay", "Timing")]
public sealed class Delay : GameplayFlowNode {

    // 입력 포트: slot 0, 타입 float
    private static readonly IReadOnlyList<ValuePortDefinition> _inputs =
        new[] { new ValuePortDefinition(0, typeof(float)) };

    [SerializeField] private float delaySeconds = 1.0f;

    public override IReadOnlyList<ValuePortDefinition> GetValueInputPorts() => _inputs;

    public override async UniTask EnterAsync(CancellationToken ct) {
        // 연결된 포트값 우선, 없으면 직렬화 필드 사용
        var duration = GetInputOverrideOrDefault(0, delaySeconds);
        if (duration > 0)
            await UniTask.Delay(
                TimeSpan.FromSeconds(duration),
                cancellationToken: ct
            );
    }
}