Skip to main content

11 Chain Event: Sequential Execution Pipeline

๐Ÿ“‹ Overviewโ€‹

While Trigger Events execute in parallel with conditional filtering, Chain Events execute in strict sequential orderโ€”one step at a time, like a production pipeline. If any node in the chain fails its condition, delays, or encounters an error, the entire sequence pauses or terminates. This is perfect for cutscenes, weapon launch sequences, tutorial steps, or any workflow where order matters.

๐Ÿ’ก What You'll Learn
  • The difference between Chain (sequential) and Trigger (parallel) execution
  • How to use condition nodes as validation gates
  • Delay nodes for timed pauses in sequences
  • Wait-for-completion for asynchronous operations
  • Early termination patterns when conditions fail

๐ŸŽฌ Demo Sceneโ€‹

Assets/TinyGiants/GameEventSystem/Demo/11_ChainEvent/11_ChainEvent.unity

Scene Compositionโ€‹

Visual Elements:

  • ๐Ÿ”ด Turret_A (Left) - Red launcher
  • ๐Ÿ”ต Turret_B (Right) - Blue launcher
  • ๐ŸŽฏ TargetDummy - Center capsule target
  • ๐Ÿ“บ HoloDisplay - Status display panel
    • Shows "SAFELOCK READY" when safety is off
    • Shows "SAFELOCK ACTIVED" when safety is on

UI Layer (Canvas):

  • ๐ŸŽฎ Three Buttons - Bottom of the screen
    • "Launch A" โ†’ Triggers ChainEventRaiser.RequestLaunchA()
    • "Launch B" โ†’ Triggers ChainEventRaiser.RequestLaunchB()
    • "Toggle SafeLock" (Orange) โ†’ Triggers ChainEventReceiver.ToggleSafetyLock()

Game Logic Layer:

  • ๐Ÿ“ค ChainEventRaiser - Sequence initiator

    • Only references ONE entry point: 0_StartSequence
    • No knowledge of downstream pipeline steps
  • ๐Ÿ“ฅ ChainEventReceiver - Step executor

    • Contains 5 methods for each pipeline stage
    • Exposes IsSafetyCheckPassed property for condition validation
    • Contains isSafetyLockDisengaged flag (toggle-able)

๐ŸŽฎ How to Interactโ€‹

The 5-Step Launch Protocolโ€‹

One root event (0_StartSequence) triggers a sequential pipeline with validation, delays, and async waiting.


Step 1: Enter Play Modeโ€‹

Press the Play button in Unity.

Initial State:

  • Safety lock: DISENGAGED (default)
  • HoloDisplay: "SAFELOCK READY"
  • Both turrets idle

Step 2: Test Successful Launch (Safety Off)โ€‹

Current State Check:

  • Ensure HoloDisplay shows "SAFELOCK READY"
  • If not, click "Toggle SafeLock" to turn safety OFF

Click "Launch A":

Sequential Execution:

[Step 1: System Check] - Immediate

  • ๐Ÿ” Condition Node evaluates ChainEventReceiver.IsSafetyCheckPassed property
  • Property checks isSafetyLockDisengaged flag
  • Result: TRUE โœ…
  • Console: [Chain Step 1] Turret_A Checking...
  • Chain proceeds to Step 2

[Step 2: Charge] - 1.0s Delay

  • โฑ๏ธ Delay Node pauses execution for 1.0 second
  • VFX: Charging particle effect spawns at turret
  • Console: [Chain Step 2] Turret_A Charging...
  • Graph waits exactly 1.0s before continuing
  • After delay, chain proceeds to Step 3

[Step 3: Fire] - Immediate

  • ๐Ÿš€ Projectile instantiated and launched toward target
  • Muzzle flash VFX at turret
  • Console: [Chain Step 3] Turret_A FIRED payload: 500
  • Projectile travels to target
  • Chain immediately proceeds to Step 4

[Step 4: Cool Down] - Wait For Completion

  • ๐Ÿ’จ Steam VFX particle system spawns
  • ๐Ÿ• Wait Node - Graph pauses until VFX completes (2.0s)
  • Console: [Chain Step 4] Turret_A Cooldowning.
  • Unlike delay (fixed time), this waits for actual VFX completion
  • After steam finishes, chain proceeds to Step 5

[Step 5: Archive] - Immediate (Arguments Blocked)

  • ๐Ÿ“ Final logging step
  • PassArgument = FALSE in graph โ†’ receives default/null values
  • Console: [Chain Step 5] Archived. Data Status: CLEAN
  • Turret unlocked for next use
  • Chain completes successfully โœ…

Timeline:

0.0s  โ†’ Step 1: System Check (instant)
0.0s โ†’ Step 2: Charge starts
1.0s โ†’ Step 3: Fire (after charge delay)
1.0s โ†’ Step 4: CoolDown starts
3.0s โ†’ Step 5: Archive (after steam VFX ~2s)
3.0s โ†’ Sequence complete

Result: โœ… Full 5-step launch sequence executed successfully.


Step 3: Test Failed Launch (Safety On)โ€‹

Click "Toggle SafeLock":

  • Safety flag changes: isSafetyLockDisengaged = false
  • HoloDisplay updates: "SAFELOCK ACTIVED"
  • UI button color changes to orange (visual warning)
  • Console: [Chain Settings] Safety Lock Disengaged: False

Click "Launch B":

Sequential Execution:

[Step 1: System Check] - FAILS โŒ

  • ๐Ÿ” Condition Node evaluates ChainEventReceiver.IsSafetyCheckPassed
  • Property checks isSafetyLockDisengaged โ†’ finds FALSE
  • Property executes failure feedback:
    • ๐Ÿšจ Red alarm vignette flashes 3 times
    • Alarm sound plays
    • Console: [Chain Blocked] Safety Check Failed. Sequence stopped immediately.
  • Condition returns FALSE
  • ๐Ÿ›‘ CHAIN TERMINATES HERE

[Steps 2-5] - NEVER EXECUTE

  • โŒ No charging VFX
  • โŒ No projectile fired
  • โŒ No steam cooldown
  • โŒ No archive log

Result: โŒ Launch aborted at gate. Steps 2-5 never ran.

๐Ÿ”ด Critical Chain Behavior

When a Chain node's condition fails:

  1. Immediate Termination - Execution stops at that node
  2. No Downstream Execution - Subsequent nodes never run
  3. No Partial Completion - All-or-nothing behavior
  4. Early Cleanup - Resources unlocked immediately

This is fundamentally different from Trigger Events, where failed conditions just skip individual branches while others continue.


๐Ÿ—๏ธ Scene Architectureโ€‹

Chain vs Trigger: The Fundamental Differenceโ€‹

Trigger Event (Parallel):

โšก Root Event: OnInteraction
โ”‚
โ”œโ”€ ๐Ÿ”ฑ Branch A: [ ๐Ÿ›ก๏ธ Guard: `HasKey == true` ]
โ”‚ โ””โ”€ ๐Ÿš€ Action: OpenDoor() โž” โœ… Condition Passed: Executing...
โ”‚
โ”œโ”€ ๐Ÿ”ฑ Branch B: [ ๐Ÿ›ก๏ธ Guard: `PlayerLevel >= 10` ]
โ”‚ โ””โ”€ ๐Ÿš€ Action: GrantBonusXP() โž” โŒ Condition Failed: Branch Skipped
โ”‚
โ””โ”€ ๐Ÿ”ฑ Branch C: [ ๐Ÿ›ก๏ธ Guard: `Always True` ]
โ””โ”€ ๐Ÿš€ Action: PlaySound("Click") โž” โœ… Condition Passed: Executing...
โ”‚
๐Ÿ“Š Summary: 2 Paths Executed | 1 Path Skipped | โšก Timing: Concurrent

Chain Event (Sequential):

๐Ÿ† Initiation: Root Event
โ”‚
โ”œโ”€ 1๏ธโƒฃ [ Step 1 ] โž” ๐Ÿ›ก๏ธ Guard: `Condition A`
โ”‚ โ””โ”€ โณ Status: WAIT for completion... โœ… Success
โ”‚
โ”œโ”€ 2๏ธโƒฃ [ Step 2 ] โž” ๐Ÿ›ก๏ธ Guard: `Condition B`
โ”‚ โ””โ”€ โณ Status: WAIT for completion... โœ… Success
โ”‚
โ”œโ”€ 3๏ธโƒฃ [ Step 3 ] โž” ๐Ÿ›ก๏ธ Guard: `Condition C`
โ”‚ โ””โ”€ โณ Status: WAIT for completion... โŒ FAILED!
โ”‚
โ””โ”€ ๐Ÿ›‘ [ TERMINATED ] โž” Logic Chain Halts
โ””โ”€ โญ๏ธ Step 4: [ SKIPPED ]
โ”‚
๐Ÿ“Š Final Result: Aborted at Step 3 | โณ Mode: Strict Blocking

When to Use Each:

PatternUse ChainUse Trigger
Cutsceneโœ… Sequential shotsโŒ Steps out of order
Combat SystemโŒ Rigid order not neededโœ… Parallel systems
Tutorialโœ… Must finish step 1 before step 2โŒ Steps can overlap
Weapon Chargeโœ… Charge โ†’ Fire โ†’ CooldownโŒ Order matters
AchievementโŒ Independent checksโœ… Multiple triggers

Event Definitionsโ€‹

Game Event Editor

Event NameTypeRoleStep
0_StartSequenceGameEvent<GameObject, DamageInfo>Root (Gold)Entry
1_SystemCheckGameEvent<GameObject, DamageInfo>Chain (Green)1
2_ChargeGameEvent<GameObject, DamageInfo>Chain (Green)2
3_FireGameEvent<GameObject, DamageInfo>Chain (Green)3
4_CoolDownGameEvent<GameObject, DamageInfo>Chain (Green)4
5_ArchiveGameEvent<GameObject, DamageInfo>Chain (Green)5

Key Insight:

  • Root raises the chain
  • Chain nodes auto-trigger sequentially
  • Code only calls .Raise() on rootโ€”graph handles rest

Flow Graph Configurationโ€‹

Click "Flow Graph" button to visualize the sequential pipeline:

Flow Graph Overview

Graph Structure (Left to Right):

Node 1: 0_StartSequence (Root, Red)

  • Entry point raised by code
  • Type: GameEvent<GameObject, DamageInfo>
  • Connects to first chain node

Node 2: 1_SystemCheck (Chain, Green)

  • โœ… Condition Node - Gate keeper
  • Condition: ChainEventReceiver.IsSafetyCheckPassed == true
    • Evaluates scene object property at runtime
    • If false โ†’ chain breaks immediately
  • Action: ChainEventReceiver.OnSystemCheck(sender, args)
  • Green checkmark icon indicates condition enabled
  • PassArgument: โœ“ Pass (full data forwarded)

Node 3: 2_Charge (Chain, Green)

  • โฑ๏ธ Delay Node - Timed pause
  • Delay: 1.0 seconds (shown as โฑ๏ธ 1s icon)
  • Action: ChainEventReceiver.OnStartCharging(sender, args)
  • Graph freezes here for exactly 1 second
  • PassArgument: โœ“ Pass

Node 4: 3_Fire (Chain, Green)

  • ๐ŸŽฏ Action Node - Standard execution
  • Action: ChainEventReceiver.OnFireWeapon(sender, args)
  • No delay, no condition
  • Executes immediately after previous step
  • PassArgument: โœ“ Pass

Node 5: 4_CoolDown (Chain, Green)

  • ๐Ÿ• Wait Node - Async completion
  • Delay: 0.5s (minimum wait)
  • WaitForCompletion: โœ“ Checked (shown as โฑ๏ธ 1s icon)
    • Graph waits for receiver coroutine to finish
    • Not a fixed timerโ€”waits for actual completion signal
  • Action: ChainEventReceiver.OnCoolDown(sender, args)
  • PassArgument: โœ“ Pass

Node 6: 5_Archive (Chain, Green)

  • ๐Ÿ”’ Filter Node - Data sanitization
  • Action: ChainEventReceiver.OnSequenceArchived(sender, args)
  • PassArgument: ๐Ÿ”ด Static (argument blocked)
    • Even though previous nodes passed full data
    • This node receives default/null values
    • Demonstrates data firewall at end of chain
  • Final stepโ€”no downstream nodes

Connection Lines:

  • ๐ŸŸข Green "CHAIN" lines - Sequential flow
    • Each output port connects to next input port
    • Linear topologyโ€”no branching
    • Execution follows line left-to-right

Legend:

  • ๐Ÿ”ด Root Node - Entry point (raised by code)
  • ๐ŸŸข Chain Node - Auto-triggered in sequence
  • โœ… Checkmark Icon - Condition enabled
  • โฑ๏ธ Clock Icon - Delay or wait configured
  • ๐Ÿ”’ Static Icon - Arguments blocked
๐ŸŽจ Visual Pipeline Benefits

The Chain Graph provides instant understanding of:

  • Sequential Order - Left-to-right flow shows exact execution order
  • Validation Gates - Condition nodes act as checkpoints
  • Timing Control - Delay/wait icons show pause points
  • Data Flow - PassArgument toggles show where data is filtered
  • Failure Points - Condition nodes show where chain can break

This is infinitely cleaner than reading a coroutine with nested yield return statements!


Sender Setup (ChainEventRaiser)โ€‹

Select the ChainEventRaiser GameObject:

ChainEventRaiser Inspector

Chain Entry Point:

  • Sequence Start Event: 0_StartSequence
    • Tooltip: "The Start Node of the Chain Graph"
    • Only references the rootโ€”downstream is handled by graph

Turrets:

  • Turret A: Turret_A (GameObject), Head A (Transform)
  • Turret B: Turret_B (GameObject), Head B (Transform)

Targeting:

  • Hit Target: TargetDummy (Transform)

Critical Observation: Like Trigger demos, sender only knows about ONE event. The 5-step pipeline is completely abstracted into the graph.


Receiver Setup (ChainEventReceiver)โ€‹

Select the ChainEventReceiver GameObject:

ChainEventReceiver Inspector

Scene References:

  • Chain Event Raiser: ChainEventRaiser (for unlock callbacks)
  • Holo Text: LogText (TextMeshPro) - displays lock status

Target References:

  • Target Dummy, Target Rigidbody

VFX & Projectiles:

  • Projectile Prefab: Projectile (TurretProjectile)
  • Charge VFX: TurretBuffAura (Particle System) - step 2
  • Fire VFX: MuzzleFlashVFX (Particle System) - step 3
  • Steam VFX: SteamVFX (Particle System) - step 4
  • Hit Normal/Crit VFX, Floating Text Prefab

Audio:

  • Hit Clip, UI Clip, Alarm Clip

Screen:

  • Screen Group: AlarmVignette (CanvasGroup) - red flash on failure

Simulation Settings:

  • โœ… Is Safety Lock Disengaged: TRUE (default)
    • Controls whether Step 1 condition passes
    • Toggle-able via "Toggle SafeLock" button

๐Ÿ’ป Code Breakdownโ€‹

๐Ÿ“ค ChainEventRaiser.cs (Sender)โ€‹

using UnityEngine;
using TinyGiants.GameEventSystem.Runtime;

public class ChainEventRaiser : MonoBehaviour
{
[Header("Chain Entry Point")]
[Tooltip("The Start Node of the Chain Graph.")]
[GameEventDropdown]
public GameEvent<GameObject, DamageInfo> sequenceStartEvent;

[Header("Turrets")]
public GameObject turretA;
public GameObject turretB;
// ... head transforms ...

private bool _isBusyA;
private bool _isBusyB;

/// <summary>
/// UI Button A: Request Launch for Turret A.
///
/// CRITICAL: Only raises the ROOT event.
/// The Chain Graph orchestrates all 5 downstream steps automatically.
/// </summary>
public void RequestLaunchA()
{
if (sequenceStartEvent == null) return;

Debug.Log("<color=cyan>[Raiser] Requesting Launch Protocol A...</color>");
_isBusyA = true;

// Build the data payload
DamageInfo info = new DamageInfo(500f, true, DamageType.Physical,
hitTarget.position, "Commander");

// THE MAGIC: Single .Raise() starts entire 5-step chain
// Graph automatically executes:
// 1. System Check (with condition)
// 2. Charge (with 1s delay)
// 3. Fire (immediate)
// 4. Cool Down (with wait-for-completion)
// 5. Archive (with blocked arguments)
sequenceStartEvent.Raise(turretA, info);
}

/// <summary>
/// UI Button B: Request Launch for Turret B.
/// Same logic, different turret.
/// </summary>
public void RequestLaunchB()
{
if (sequenceStartEvent == null) return;

Debug.Log("<color=orange>[Raiser] Requesting Launch Protocol B...</color>");
_isBusyB = true;

DamageInfo info = new DamageInfo(200f, false, DamageType.Physical,
hitTarget.position, "Commander");
sequenceStartEvent.Raise(turretB, info);
}

// Unlock methods called by receiver when sequence completes or fails
public void UnlockTurretA() => _isBusyA = false;
public void UnlockTurretB() => _isBusyB = false;
}

Key Points:

  • ๐ŸŽฏ Single Event Reference - Only knows root event
  • ๐Ÿ“ก Zero Pipeline Knowledge - No idea about 5 steps
  • ๐Ÿ”“ Unlock Callbacks - Receiver signals completion/failure
  • ๐ŸŽฌ Maximum Decoupling - All sequence logic in graph

๐Ÿ“ฅ ChainEventReceiver.cs (Listener)โ€‹

using UnityEngine;
using System.Collections;

public class ChainEventReceiver : MonoBehaviour
{
[Header("Simulation Settings")]
[Tooltip("If TRUE, passes check. If FALSE, chain breaks at Step 1.")]
public bool isSafetyLockDisengaged = true;

/// <summary>
/// Property accessed by '1_SystemCheck' Node Condition.
///
/// Graph configuration: Scene Object โ†’ Property โ†’ IsSafetyCheckPassed
///
/// CRITICAL: This is evaluated BEFORE the node action executes.
/// If this returns false, the chain terminates immediately.
/// </summary>
public bool IsSafetyCheckPassed
{
get
{
bool result = true;

if (!isSafetyLockDisengaged)
{
// FAIL PATH: Safety lock is engaged
result = false;

Debug.LogWarning(
"<color=red>[Chain Blocked] Safety Check Failed. " +
"Sequence stopped immediately.</color>");

// Visual feedback for failure
StopCoroutine(nameof(ScreenRoutine));
if (screenGroup) StartCoroutine(ScreenRoutine());
}

return result;
}
}

/// <summary>
/// Toggles the safety lock status. Bind this to UI Button.
/// </summary>
public void ToggleSafetyLock()
{
if (UIClip) _audioSource.PlayOneShot(UIClip);

isSafetyLockDisengaged = !isSafetyLockDisengaged;

// Update UI
string text = isSafetyLockDisengaged ? "SAFELOCK READY" : "SAFELOCK ACTIVED";
if (holoText) holoText.text = text;

Debug.Log($"[Chain Settings] Safety Lock Disengaged: {isSafetyLockDisengaged}");
}

/// <summary>
/// [Chain Step 1] System Check
/// Bound to '1_SystemCheck' chain node.
///
/// Note: This action runs AFTER the condition passed.
/// If condition failed, this method never executes.
/// </summary>
public void OnSystemCheck(GameObject sender, DamageInfo args)
{
bool isA = sender != null && sender.name.Contains("Turret_A");

// If we reach here, condition passed
// But we still handle potential edge cases
if (!IsSafetyCheckPassed)
{
// Unlock turret since sequence failed
if (isA) chainEventRaiser.UnlockTurretA();
else chainEventRaiser.UnlockTurretB();
}

Debug.Log($"[Chain Step 1] {sender.name} Checking...");
}

/// <summary>
/// [Chain Step 2] Charge
/// Bound to '2_Charge' chain node with 1.0s delay.
///
/// The graph pauses for 1 second BEFORE calling this method.
/// When this executes, 1.0s has already elapsed.
/// </summary>
public void OnStartCharging(GameObject sender, DamageInfo args)
{
if (chargeVFX)
{
var vfx = Instantiate(chargeVFX, sender.transform.position + Vector3.up * 1.5f,
Quaternion.identity);
vfx.transform.SetParent(sender.transform);
vfx.Play();
Destroy(vfx.gameObject, 1.2f);
}

Debug.Log($"[Chain Step 2] {sender.name} Charging...");
}

/// <summary>
/// [Chain Step 3] Fire
/// Bound to '3_Fire' chain node.
///
/// Spawns projectile and launches toward target.
/// This executes immediately after Step 2 completes.
/// </summary>
public void OnFireWeapon(GameObject sender, DamageInfo args)
{
// Spawn muzzle flash
if (fireVFX)
{
Vector3 spawnPos = sender.transform.position +
sender.transform.forward * 1.5f + Vector3.up * 1.5f;
var vfx = Instantiate(fireVFX, spawnPos, sender.transform.rotation);
vfx.Play();
Destroy(vfx.gameObject, 2.0f);
}

// Launch projectile
if (projectilePrefab != null)
{
var muzzlePos = sender.transform.Find("Head/Barrel/MuzzlePoint");
var shell = Instantiate(projectilePrefab, muzzlePos.position,
sender.transform.rotation);

shell.Initialize(args.hitPoint, 20f, () =>
{
// Impact callback
if (hitClip) _audioSource.PlayOneShot(hitClip);

// Spawn hit VFX, floating text, apply physics...
ParticleSystem vfxToPlay = args.isCritical ? hitCritVFX : hitNormalVFX;

if (args.isCritical)
StartCoroutine(ShakeCameraRoutine(0.2f, 0.4f));

// ... (VFX, physics, text logic) ...
});
}

Debug.Log($"[Chain Step 3] {sender.name} FIRED payload: {args.amount}");
}

/// <summary>
/// [Chain Step 4] Cool Down
/// Bound to '4_CoolDown' chain node with WaitForCompletion.
///
/// The graph waits for this coroutine to finish before proceeding to Step 5.
/// Unlike delay (fixed time), this waits for actual task completion.
/// </summary>
public void OnCoolDown(GameObject sender, DamageInfo args)
{
if (steamVFX)
{
var vfx = Instantiate(steamVFX, sender.transform.position + Vector3.up,
Quaternion.Euler(-90, 0, 0));
vfx.Play();
Destroy(vfx.gameObject, 2.0f);
}

Debug.Log($"[Chain Step 4] {sender.name} Cooldowning.");
}

/// <summary>
/// [Chain Step 5] Archive
/// Bound to '5_Archive' chain node with PassArgument = FALSE.
///
/// CRITICAL: Even though previous steps passed full DamageInfo,
/// this node receives DEFAULT/NULL values due to graph configuration.
///
/// Demonstrates data firewallโ€”can sanitize sensitive data at end of chain.
/// </summary>
public void OnSequenceArchived(GameObject sender, DamageInfo args)
{
bool isA = sender != null && sender.name.Contains("Turret_A");

// Unlock turret for next use
if (isA) chainEventRaiser.UnlockTurretA();
else chainEventRaiser.UnlockTurretB();

// Check if data was successfully blocked
bool isClean = (args == null || args.amount == 0);
string logMsg = isClean ? "<color=cyan>CLEAN</color>" : "<color=red>LEAKED</color>";

Debug.Log($"[Chain Step 5] Archived. Data Status: {logMsg}");
}

private IEnumerator ScreenRoutine()
{
// Red alarm vignette flash animation
int flashes = 3;
float flashDuration = 0.5f;

for (int i = 0; i < flashes; i++)
{
if (alarmClip) _audioSource.PlayOneShot(alarmClip);

// Sine wave alpha animation
float t = 0f;
while (t < flashDuration)
{
t += Time.deltaTime;
float alpha = Mathf.Sin((t / flashDuration) * Mathf.PI);
screenGroup.alpha = alpha * 0.8f;
yield return null;
}

screenGroup.alpha = 0f;
yield return new WaitForSeconds(0.1f);
}
}
}

Key Points:

  • ๐ŸŽฏ 5 Independent Methods - Each handles one pipeline stage
  • โœ… Property for Condition - IsSafetyCheckPassed evaluated by graph
  • โฑ๏ธ Timing Agnostic - Methods don't know about delays
  • ๐Ÿ”’ Data Firewall - Step 5 receives sanitized data
  • ๐ŸŽฌ Completion Callbacks - Unlocks turrets on success/failure

๐Ÿ”‘ Key Takeawaysโ€‹

ConceptImplementation
๐Ÿ”— Sequential ExecutionNodes execute one-by-one in strict order
โœ… Validation GatesCondition nodes terminate chain if failed
โฑ๏ธ Delay NodesFixed-time pauses between steps
๐Ÿ• Wait NodesAsync completion waiting (not fixed time)
๐Ÿ”’ Data FilteringPassArgument controls data flow per node
๐Ÿ›‘ Early TerminationFailed condition stops entire chain
๐ŸŽฏ All-or-NothingChain completes fully or terminates early
๐ŸŽ“ Design Insight

Chain Events are perfect for:

  • Cutscenes - Shot 1 โ†’ Shot 2 โ†’ Shot 3 in exact order
  • Weapon Sequences - Charge โ†’ Fire โ†’ Cooldown โ†’ Reload
  • Tutorial Steps - Must complete step N before step N+1
  • Crafting Recipes - Sequential ingredient addition
  • Boss Phases - Phase transitions with validation
  • Spell Casting - Channeling โ†’ Cast โ†’ Effect โ†’ Recovery

Chain vs Coroutine: Instead of writing:

IEnumerator LaunchSequence()
{
if (!SafetyCheck()) yield break;
Charge();
yield return new WaitForSeconds(1.0f);
Fire();
yield return StartCoroutine(CoolDown());
Archive();
}

Use a Chain Graph where:

  • Timing is visible and editable by designers
  • Conditions are visual checkpoints, not hidden if statements
  • Async waits are configurable, not hardcoded
  • Entire pipeline is debuggable via graph visualization
โš ๏ธ Chain Gotchas
  1. Blocking Behavior: If Step 3 has a bug and never completes, Steps 4-5 never run
  2. Condition Timing: Conditions evaluate BEFORE node actionโ€”can't use action's side effects
  3. No Parallel Branches: Can't execute Step 2A and Step 2B simultaneously (use Trigger for that)
  4. Delay Stacking: Multiple delays add upโ€”3 nodes with 1s each = 3s total wait
  5. Early Exit Cleanup: Always unlock resources in condition failure paths

๐ŸŽฏ What's Next?โ€‹

You've mastered sequential chain execution. The examples series continues with more advanced patterns.

Next Chapter: Continue exploring advanced demos in 12 Multi Database