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.

๐ฏ 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:

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โ
| Feature | Benefit |
|---|---|
| ๐จ Visual Building | Designers create logic without code |
| ๐ High Performance | Compiles to Expression Trees (zero reflection) |
| ๐ Reusable | Same condition applies to all event actions |
| ๐งช Live Testing | Tweak values in Inspector, see results immediately |
| ๐ Type-Safe | Auto-validates type compatibility |
๐๏ธ Tree Structureโ
The condition tree is built from two node types:

๐ณ Group Nodesโ
Combine multiple conditions using AND/OR logic.
Logic Types:
- AND Logic
- OR Logic
All child conditions must evaluate to TRUE.
Visual: ๐ข Green border
Use: "Must satisfy ALL requirements"
Any child condition can evaluate to TRUE.
Visual: ๐ Orange border
Use: "Satisfy ANY requirement"
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 Mode | Visual Style | Best For... |
|---|---|---|
| ๐ Collapsed | Summary Text (e.g., Health < 50) | Quick overview of complex logic chains. |
| ๐ ๏ธ Expanded | Detailed Editor (Dropdowns, Fields) | Modifying specific parameters and sources. |
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
- Scene Type
- Random 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.
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>
| Root | Path Example | Data Type |
|---|---|---|
| Sender | Sender.Transform.position | Vector3 |
| Argument | Argument.amount | float |
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:
| Category | Supported Types |
|---|---|
| Primitives | int, float, double, long, bool, string |
| Math | Vector2, Vector3, Quaternion, Color |
| Unity | GameObject, Transform, Component references |
| Logic | Enums (with dropdowns), [Serializable] C# Classes |
Any public Field or Property in a [Serializable] class is automatically exposed in the deep-link picker.
๐ฌ Scene Typeโ
Access runtime data from GameObjects or Components in the scene.
How to Useโ
Step 1: Drag GameObject or Component from Hierarchy into the object field.
Step 2: Click "Select Property..." to browse available members.
GameObject Exampleโ
Drag PlayerController GameObject:
๐ฆ GameObject (Instance)
โโ ๐ฆ (this GameObject) โ The reference itself
โโ โ
activeSelf โ bool
โโ ๐ค tag โ string
โโ ๐ข layer โ int
๐ Transform (Component)
โโ ๐ position โ Vector3
โโ ๐ localScale โ Vector3
โโ ๐ childCount โ int
๐งฉ PlayerController (Script)
โโ ๐ข Health โ float
โโ ๐ก๏ธ Shield โ float
โโ ๐
Level โ int
โโ โ
HasFireResistance โ bool
โ
โโ โก IsInDangerZone() โ bool (Method)
โโ โก IsCriticallyWounded() โ bool (Method)
Usage:
Player.Health < 50 โ Health check
Player.Level >= 10 โ Level requirement
Player.IsInDangerZone() == true โ Complex check via method
Bool Method Support โจโ
Zero-parameter methods returning bool appear in the dropdown!
Example:
// In your component
public bool IsInDangerZone() {
return Health < 20 && Shield == 0 && !IsInvincible;
}
In Condition Tree:
Player.IsInDangerZone() == true
This encapsulates complex logic in a single method call instead of building it visually.
Component Exampleโ
Drag GameManager Component:
๐๏ธ GameManager (Global System)
โโ ๐ CurrentState โ GameState (Enum)
โโ ๐ CurrentWave โ int
โโ ๐
DifficultyLevel โ int
โ
โโ โก IsInCombat() โ bool (Method)
โโ โก IsHardMode() โ bool (Method)
Usage:
GameManager.CurrentState == Playing
GameManager.IsInCombat() == true
GameManager.DifficultyLevel >= 3
Important Limitationโ
โ ๏ธ Scene Type requires objects to exist at scene load time.
โ
Works: Objects in scene hierarchy (exist at initialization)
โ Fails: Runtime-instantiated objects (don't exist yet)
Solution: Use Event Argument for runtime objects
๐ฒ Random Typeโ
Purpose: Generate random values at execution time.
Two Modesโ
Mode 1: Range
Generate random number within bounds.

Configuration:
- Min: Lower bound
- Max: Upper bound
- Integer: Check for whole numbers, uncheck for decimals
Mode 2: List
Pick random item from predefined values.

Configuration:
- Data Type: Choose type (int, float, string, bool, etc.)
- List Items: Add/remove values with +/- buttons
Use Casesโ
Critical Hit Chance:
Random(0~100) > 90 โ 10% chance
Damage Variance:
Random(0~10) โ Add random bonus damage
Dynamic Events:
Random List[Easy, Normal, Hard] โ Randomize difficulty
Details
๐ Operator
How to compare: The logic between Source and Target.๐ Available Operatorsโ
Numeric (6)
For numbers (int, float, double, long):
| Operator | Symbol | Example |
|---|---|---|
| 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:
| Operator | Symbol | Example |
|---|---|---|
| Equals | == | Name == "Hero" |
| Not Equals | != | Tag != "Enemy" |
| Starts With | Starts With | Name Starts With "Player_" |
| Ends With | Ends With | File Ends With ".png" |
| Contains | Contains (โ) | 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:
| Operator | Symbol | Purpose |
|---|---|---|
| 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
- Scene Type
- Random Type
- Constant
๐งฌ Event Argument (Data Payload)โ
Like Source, please refer to the relevant configuration introduction in Source for specific details
๐ฌ Scene Typeโ
Like Source, please refer to the relevant configuration introduction in Source for specific details
๐ฒ Random Typeโ
Like Source, please refer to the relevant configuration introduction in Source for specific details
๐ Constantโ
Fixed comparison value.
Note: Only available as Target (right side), not Source.
Two Modesโ
Mode 1: Single Value
Enter one fixed value.

Data Types: Int, Float, Double, String, Bool
Mode 2: List
Define multiple acceptable values (for "In List" operator).

Configuration:
- Data Type: Type for all list items
- + / -: Add/remove items
Use Casesโ
Thresholds:
Health < 50.0
Exact Matches:
Name == "Hero"
Multiple Values:
Type In List [Fire, Void, Lightning]
Additional support type: Constant Type**๏ผonly available for Target๏ผ**
Some operators restrict target type:
-
Numeric operators (
>,<, etc.) require single values -
"In List" operator requires list types
๐จ 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
Hybrid Approach (Recommended)โ
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.
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