Skip to main content

Visual Condition Tree

Build complex boolean logic visually to control whether event actions should execute. Create sophisticated runtime checks through an intuitive interfaceโ€”no coding required.

Visual Condition Tree


๐ŸŽฏ Overviewโ€‹

The Visual Condition Tree is a logic gate system that evaluates runtime conditions before executing event actions.

The Problem It Solvesโ€‹

Traditional Approach (scattered logic):

// Logic buried in scripts, hard to modify
if (damageInfo.amount > 20 &&
(damageInfo.isCritical || damageInfo.type == DamageType.Fire) &&
playerController.Health < 50 &&
gameManager.IsInCombat()) {
// Execute actions
}

Visual Approach:

Visual Condition Tree


Build an exampleโ€‹

Event: OnPlayerDamaged

Event Types:

  • GameEvent<GameObject, DamageInfo> (GameObject sender)
  • GameEvent<PlayerStats, DamageInfo> (Custom sender)

Data Structures:

// Damage type enumeration
public enum DamageType {
Physical,
Fire,
Void
}

// Damage information payload
public class DamageInfo {
public float amount; // Damage value
public bool isCritical; // Critical hit flag
public DamageType type; // Damage type
public Vector3 hitPoint; // Impact location
public string attacker; // Attacker name
}

// Custom sender type (alternative to GameObject)
public class PlayerStats {
public string playerName;
public int level;
public int factionId;
}

Goal: Trigger warning effects when player takes significant damage under specific conditions.


Key Benefitsโ€‹

FeatureBenefit
๐ŸŽจ Visual BuildingDesigners create logic without code
๐Ÿš€ High PerformanceCompiles to Expression Trees (zero reflection)
๐Ÿ”„ ReusableSame condition applies to all event actions
๐Ÿงช Live TestingTweak values in Inspector, see results immediately
๐Ÿ”’ Type-SafeAuto-validates type compatibility

๐Ÿ—๏ธ Tree Structureโ€‹

The condition tree is built from two node types:

Node Types

๐ŸŒณ Group Nodesโ€‹

Combine multiple conditions using AND/OR logic.

Logic Types:

All child conditions must evaluate to TRUE.

Visual: ๐ŸŸข Green border

Use: "Must satisfy ALL requirements"

Toggle Logic: Click the logic button (AND/OR) to switch.

Nesting: Groups can contain other groupsโ€”build complex logic with unlimited depth.

Add Nodes: Use + Condition or + Group buttons on each group.


โš–๏ธ Comparison Nodesโ€‹

Comparison Nodes are the fundamental building blocks of your event logic. Each node performs a single boolean check (True/False) to determine if the event actions should proceed.

๐Ÿ—๏ธ Anatomy of a Comparisonโ€‹

Every node follows a standard tripartite structure, making complex logic easy to read at a glance.

[ ๐ŸŸฆ Source(Left Operand) ] [ Operator ] [ ๐ŸŸง Target (Right Operand) ]

Practical Example: Imagine an event that only triggers if a hit is powerful enough: Argument.amount > 20.0

  • ๐Ÿ” Source: Argument.amount โ€” The raw damage value passed by the GameEvent<float>
  • ๐Ÿ“ Operator: > โ€” The logical rule (Greater Than)
  • ๐ŸŽฏ Target: 20.0 โ€” The constant threshold or another variable to compare against

๐Ÿ‘“ View Modesโ€‹

The editor UI adapts to your needs, balancing readability with precision control.

View ModeVisual StyleBest For...
๐Ÿ“– CollapsedSummary Text (e.g., Health < 50)Quick overview of complex logic chains.
๐Ÿ› ๏ธ ExpandedDetailed Editor (Dropdowns, Fields)Modifying specific parameters and sources.
Interaction Hint

Simply Click on any comparison block to toggle between these two views. This allows you to keep your workspace clean while retaining the ability to deep-dive into settings.


๐Ÿ“ Structure Configurationโ€‹

Details

๐Ÿ“Œ Source What to compare: The left operand of your boolean expression.

Configure what value to check by selecting a Source Type:

๐Ÿงฌ Event Argument (Data Payload)โ€‹

The Argument system allows you to drill down into the event's data payload to extract specific values for conditions and actions.

Availability

Data access is exclusive to typed events: GameEvent<T> or GameEvent<TSender, TArgs>.

๐Ÿ”ข Single Parameter Eventsโ€‹

Signature: GameEvent<DamageInfo>

When an event carries a single object, you can access the object itself or any of its public members.

Data Structure Example:

๐Ÿ“ฆ (this Argument)      โž” Full DamageInfo object
โ”œโ”€โ”€ ๐Ÿ”ข amount โž” float
โ”œโ”€โ”€ โœ… isCritical โž” bool
โ”œโ”€โ”€ ๐Ÿท๏ธ type โž” DamageType (Enum)
โ”œโ”€โ”€ ๐Ÿ“ hitPoint โž” Vector3
โ””โ”€โ”€ ๐Ÿ‘ค attacker โž” string

๐Ÿ‘ฅ Sender Events (Context-Aware)โ€‹

Sender events provide two distinct roots for data access: Sender (Who) and Argument (What).

๐ŸŽฎ Case A: GameObject Senderโ€‹

Signature: GameEvent<GameObject, DamageInfo>

RootPath ExampleData Type
SenderSender.Transform.positionVector3
ArgumentArgument.amountfloat

Visual Hierarchy:

๐Ÿ‘ฅ Sender
โ”œโ”€โ”€ ๐Ÿ†” tag โž” string
โ”œโ”€โ”€ ๐ŸŸข activeSelf โž” bool
โ””โ”€โ”€ ๐Ÿ“ Transform
โ”œโ”€โ”€ ๐Ÿ“ position โž” Vector3
โ””โ”€โ”€ ๐Ÿ“‚ childCountโž” int
๐Ÿ”ข Argument
โ”œโ”€โ”€ ๐Ÿ”ข amount โž” float
โ””โ”€โ”€ โœ… isCritical โž” bool
๐Ÿ›ก๏ธ Case B: Custom C# Sender (Advanced)โ€‹

Signature: GameEvent<PlayerStats, DamageInfo>

๐Ÿš€ Why it's special: Unlike traditional systems, you are not tied to GameObjects. Use any Pure C# Class as a sender for decoupled, logic-first architecture.

  • ๐Ÿ’Ž Pure Logic โ€” Works with non-MonoBehaviour classes.
  • ๐ŸŒ Network Ready โ€” Ideal for PlayerData or NetworkAgent sync.
  • ๐Ÿค– AI Agents โ€” Track internal state without scene dependencies.

๐Ÿงญ Deep Property Accessโ€‹

Precision Navigation. Navigate nested structures up to 5 levels deep with high-performance reflection.

Example: Directional Check

  • Path: Argument.hitPoint.normalized.x
  • Condition: > 0.5
  • Result: ๐ŸŽฏ "Hit came from the right side."

Breadcrumb Logic: Argument (DamageInfo) โž” hitPoint (Vector3) โž” normalized (Vector3) โž” x (float)


๐Ÿ“‹ Supported Typesโ€‹

The system automatically support below types:

CategorySupported Types
Primitivesint, float, double, long, bool, string
MathVector2, Vector3, Quaternion, Color
UnityGameObject, Transform, Component references
LogicEnums (with dropdowns), [Serializable] C# Classes
Pro Tip: Custom Classes

Any public Field or Property in a [Serializable] class is automatically exposed in the deep-link picker.

Details

๐Ÿ“Œ Operator How to compare: The logic between Source and Target.

๐Ÿ“ Available Operatorsโ€‹

Numeric (6)

For numbers (int, float, double, long):

OperatorSymbolExample
Equals==Health == 100
Not Equals!=Health != 0
Greater>Damage > 20
Less<Health < 50
Greater Or Equal>=Level >= 10
Less Or Equal<=Shield <= 0

Auto-Conversion: Compatible numeric types convert automatically (int โ†” float).


String (4)

For text values:

OperatorSymbolExample
Equals==Name == "Hero"
Not Equals!=Tag != "Enemy"
Starts WithStarts WithName Starts With "Player_"
Ends WithEnds WithFile Ends With ".png"
ContainsContains (โŠƒ)Message Contains "error"

โš ๏ธ Case-sensitive: "Hero" โ‰  "hero"


Enum Support

Full enumeration support with dropdown selection!

Example:

public enum DamageType { Physical, Fire, Void }

In Condition Tree:

Source: Argument.type (DamageType)
Operator: ==
Target: DamageType.Fire (dropdown shows Physical/Fire/Void)

With Lists:

Argument.type In List [Fire, Void]
Result: TRUE if type is DamageType.Fire OR DamageType.Void

Supported Operators: ==, !=, In List (โˆˆ)


Collection (1)

Check list/array membership:

OperatorSymbolPurpose
In ListโˆˆCheck if value exists in list

Structure:

Source: Single value
Operator: In List (โˆˆ)
Target: List/Array (matching type)

Examples:

Argument.attacker In List ["Dragon", "Demon", "Lich"]
Player.Level In List [10, 20, 30, 40, 50]
Argument.type In List [Fire, Void]
๐Ÿ“Œ Target

๐Ÿงฌ Event Argument (Data Payload)โ€‹

Same as Source

Like Source, please refer to the relevant configuration introduction in Source for specific details


๐ŸŽจ Type Validationโ€‹

The system automatically validates type compatibility.

Valid Comparisons:

โœ… int == int
โœ… float > int (auto-converts)
โœ… string Contains string
โœ… DamageType == Fire (enum)
โœ… int In List<int>

Invalid Comparisons:

โŒ string > int (incompatible types)
โŒ bool Contains string (meaningless)
โŒ float In List<string> (type mismatch)

Visual Feedback: Red outline + warning text on incompatible types.


๐Ÿงฉ Bool Methods vs Visual Treeโ€‹

Two approaches to building conditionsโ€”when to use each?

Approach 1: Bool Methodsโ€‹

Best for: Complex multi-step logic.

Example:

public bool IsInDangerZone() {
bool lowHealth = Health < 20;
bool noShield = Shield == 0;
bool hasEnemies = Physics.OverlapSphere(
transform.position, 10f, enemyLayer
).Length > 0;

return lowHealth && noShield && hasEnemies;
}

In Tree: Player.IsInDangerZone() == true

Pros:

  • Encapsulates complexity
  • Can use Physics, raycasts
  • Unit testable
  • Code reusable

Cons:

  • Requires C# coding
  • Designers can't modify

Approach 2: Visual Treeโ€‹

Best for: Simple checks designers should control.

Example:

Pros:

  • No coding needed
  • Designer-friendly
  • Visual representation
  • Quick iteration

Cons:

  • Can't use Physics/algorithms
  • Large trees get complex

Combine both for optimal results:

Guideline:

  • Visual Tree: Thresholds, enums, simple properties
  • Bool Methods: Physics queries, complex algorithms, cross-system checks

๐Ÿ”„ Drag & Reorderโ€‹

Change execution order: Drag the handle (โ˜ฐ) on the left edge of any condition.

Why Order Matters:

AND Groups: Order doesn't affect result (all must pass).

OR Groups: Order affects short-circuit evaluation (stops at first TRUE).

Optimization Example:

โŒ Slow:
OR Group
โ”œโ”€ ExpensivePhysicsCheck() โ† Runs first (slow!)
โ””โ”€ SimpleBoolCheck โ† May never run

โœ… Fast:
OR Group
โ”œโ”€ SimpleBoolCheck โ† Runs first (fast!)
โ””โ”€ ExpensivePhysicsCheck() โ† Only if needed

Put cheap checks first in OR groups for better performance.


๐Ÿš€ Performanceโ€‹

Compilation Processโ€‹

One-time cost (scene load):

Visual Tree โ†’ Expression Tree โ†’ IL Code โ†’ Compiled Lambda

Runtime execution:

Event Fires โ†’ Call Compiled Lambda โ†’ Return TRUE/FALSE

Benchmark: Complex nested conditions execute in ~0.001ms (1 microsecond).


Why It's Fastโ€‹

Zero Reflection: Direct compiled access like hand-written C#.

Expression Trees: System generates optimized IL code at initialization.

โŒ Traditional: GetComponent() + GetField() + Invoke() per check
โœ… This System: Direct property access via compiled lambda

Result: Negligible overhead even with hundreds of events firing per frame.


๐Ÿงน Tree Managementโ€‹

  • Enable/Disable: Toggle checkbox to bypass all conditions (always TRUE).

  • Reset Tree: Click "Reset Tree" button to clear all nodes and start fresh.

  • Collapse/Expand: Click comparison blocks to toggle between summary and detail views.


โ“ Troubleshootingโ€‹

Conditions Always Return Falseโ€‹

Checklist:

  • โœ… Is "Enable Conditions" toggle checked?
  • โœ… Are there red type mismatch warnings?
  • โœ… Are Scene Type references still valid (not destroyed)?
  • โœ… Do bool methods return expected values? (add Debug.Log)

Property Not in Dropdownโ€‹

For Event Arguments:

  • Must be public field or property
  • Must be supported type

For Scene Types:

  • GameObject must exist in scene at Editor time
  • Component must be enabled
  • Property must be public
  • Methods must: return bool, zero parameters, public, instance (not static)

For Runtime Objects: Use Event Argument instead of Scene Type.


Changes Not Savingโ€‹

Common Causes:

  • Multiple Behavior Windows open (close duplicates)
  • Script compilation during editing (wait for completion)
  • Unity didn't apply SerializedProperty changes (wait before closing)

๐Ÿ“– Where It's Usedโ€‹

The Visual Condition Tree system appears in two contexts:

1. Event Behaviors โ†’ Game Event Behavior

Controls whether event actions execute:

Event Fires โ†’ Check Conditions โ†’ Execute/Skip Actions

2. Flow Nodes โ†’ Flow Node Configuration (future documentation)

Controls whether flow nodes execute:

Flow Reaches Node โ†’ Check Conditions โ†’ Execute/Skip Node

Both use the exact same condition tree system.


Best Practices

Simple Checks: Use Visual Tree for thresholds, enums, basic comparisons

Complex Logic: Use Bool Methods for Physics, algorithms, multi-step checks

Optimal Approach: Combine bothโ€”visual for simple, methods for complex

Performance: Put cheap checks first in OR groups for short-circuit optimization