Unreal Animal AI in Practice: A Complete Guide to State Machines and Interface Design

A complete breakdown of upfront design for Unreal animal AI architecture, from state enums and Blueprint interfaces to base class variables.
The article breaks down an overseas developer's upfront architectural work for building an animal AI system in Unreal, centered on three layers: state management, interface abstraction, and base class variables. The state enum `E_AnimalState` defines seven behaviors—Idle, Roaming, Investigating, Chasing, Attacking, Fleeing, and Death—covering the complete chain from patrol to escape. At the interface level, `BPI_Damageable` implements universal damage reception and reception checks, reusable for player characters; `BPI_AnimalTarget` implements animal-specific target validity, position, and threat level queries, with `IsValidAnimalTarget` performing pre-filtering before damage checks to handle scenarios like the player being knocked down or invincible. The base class `BP_AnimalBase` inherits from Character, with variables organized into five groups: basic info, movement, detection, combat, and behavior. The detection distance design reserves room for subclass differentiation and overriding. In BeginPlay, `HasAuthority` ensures initialization only on the server, and the next stage will connect behavior trees to drive actual behavior.
Building Animal AI in Unreal: State Enums, Interfaces, and Base Class Planning
When building an animal AI system in Unreal Engine, the core difficulty often isn't the behavior tree itself, but whether the underlying state management and interface abstraction are sound. Recently, an overseas developer shared their hands-on process of building animal AI for an RPG project on Bilibili, covering everything from folder organization to interface design to base class variable planning—a complete round of upfront work for an extensible AI architecture.
State Enum: Defining Every Possible Animal Behavior
The developer first created an AI_Animals directory structure under the AI folder, containing subfolders like Base, Interfaces, Enums, and Structures. This responsibility-based division gives every subsequent AI asset a clear home.
The core state enum E_AnimalState defines six behavioral states:
- Idle: The animal is currently not performing any action
- Roaming: Randomly patrolling the scene
- Investigating: Moving to a target point to search for the player after hearing a sound
- Chasing: Starting to pursue after spotting the player
- Attacking: Switching to attack state once within attack range
- Fleeing: Choosing to escape when facing multiple enemies or when health is too low
- Death: The final state after health reaches zero
This state breakdown covers the complete behavioral chain from passive patrol to active attack to survival-driven escape. The developer specifically noted that animals will choose to flee rather than fight when facing two or more players, laying the groundwork for a future threat level system.

Division of Labor Between Behavior Tree and State Machine: In Unreal's AI system, enums like E_AnimalState typically don't directly drive behavior. Instead, they serve as core data for Blackboard Keys, which the Behavior Tree reads to decide which branch to execute. Behavior trees excel at expressing hierarchical "condition-action" decisions, while enum state machines excel at expressing mutually exclusive macro patterns. Combining both is a common paradigm in UE AI.
Implementation Differences Between Roaming and Patrol: Roaming is typically implemented using NavMesh and the MoveToRandomLocation node, relying on the navigation mesh to automatically avoid obstacles. If the scene hasn't had its NavMesh baked, the animal will get stuck in place.
Threat Level and Fleeing Logic: The Fleeing state often works in conjunction with EQS (Environment Query System). The animal calculates a threat value by querying the number and distance of nearby hostile Actors, and switches state once it exceeds a threshold—directly echoing the GetAnimalThreatLevel design mentioned in the article.
Interface Design: Decoupling Damage and Target Validation Logic
Interface design is the most noteworthy part of the entire architecture. The developer created two Blueprint Interfaces, each solving problems at a different level.
BPI_Damageable: Universal Damage Reception Interface
This interface is deliberately designed to be universal, not limited to animal AI. It contains two functions:
ReceiveDamage takes three input parameters—Amount (damage value), DamageCauser (the Actor that caused the damage), and HitLocation (the hit position). This is sufficient to support the vast majority of damage calculation scenarios.
CanReceiveDamage returns a boolean, used to determine whether the target can currently receive damage. This design solves a practical problem: when the player has already been knocked down or is in an invincible state, the attacker needs to know in advance that the target is no longer valid, so it can stop attacking and have the AI return to the roaming state. The developer emphasized that this interface can also be used for player characters, achieving unified bidirectional damage management.
Difference Between Blueprint Interfaces and C++ Interfaces: The BPI_ prefix indicates this is a Blueprint Interface. It only declares function signatures without implementations—any Blueprint class implementing this interface must fill in the logic itself. This is similar to a C++ pure virtual class but lighter weight, making it suitable for cross-module decoupling.
Considerations Behind ReceiveDamage's Parameter Design: The reason DamageCauser passes an Actor rather than just a value is to allow the hit party to reverse-identify the attacker, thereby triggering aggro, retaliation, or threat level updates. HitLocation is used to spawn hit effects, calculate knockback direction, or determine weak points.
Relationship with UE's Native Damage System: Unreal comes with the ApplyDamage and AnyDamage event system. BPI_Damageable is essentially an object-oriented encapsulation of it. The benefit is that interface calls don't depend on the global functions of UGameplayStatics, giving clearer responsibility boundaries and making unit testing and implementation swapping easier.
BPI_AnimalTarget: Animal-Specific Target Interface
This is an interface exclusive to animal AI, containing two key functions:
IsValidAnimalTarget returns a boolean, used as a pre-check before calling CanReceiveDamage. Scenarios include: the player is no longer a valid target after being knocked down, the player has used a three-second invincibility skill, and so on. All logic steps between this function and damage reception will be skipped.
GetAnimalTargetLocation returns the target's exact position as a Vector.
GetAnimalThreatLevel returns the threat level as a Float. The developer gave an example: if an animal can only handle one player, it will choose to flee rather than attack when the threat level is too high.

Base Class Variable Planning: From Health to Behavioral Decisions
The animal base class BP_AnimalBase inherits from the Character class and adds two Scene Components as the attack origin and side origin. Variables are divided into five groups by function:
Basic Info Group: AnimalName (Name type), AnimalState (replicated enum, defaults to Idle), MaxHealth (defaults to 100), CurrentHealth (replicated), bIsDeath (replicated boolean).
Movement Group: WalkSpeed (150), RunSpeed (450), RoamRadius (1200).
Detection Group: SightDistance (1500), LoseTargetDistance, HearingDistance (1200). The developer deliberately set hearing distance shorter than sight distance because not all animals have better hearing than vision. However, he noted that the wolf subclass can independently extend hearing distance further, while the snake requires corresponding adjustments—this differentiated design approach is exactly the value of using the base class + subclass override pattern.

Combat Group: AttackDamage (base 20), AttackDistance (default 150), AttackCooldown, bCanBeKnockedBack (defaults to true). The developer compared the snake and wolf: the snake's attack distance is shorter, while the wolf's jumping attack distance is longer.
Behavior Group: bIsAggressive (all animals are aggressive by default), HealthThreshold (health threshold that triggers fleeing), TargetActor (replicated Actor reference).

Meaning of Replicated Variables: The article marks variables as "replicated" in several places, meaning these variables are synced from the server to the client in multiplayer games. AnimalState, CurrentHealth, bIsDeath, and TargetActor are all states that must be visible on the client, while static configurations like MaxHealth and WalkSpeed don't need replication, saving bandwidth.
Scene Component as Attack Origin: Compared to calculating attacks using the Actor's own position, adding a dedicated Scene Component allows developers to manually fine-tune the spatial positions of attack checks and side checks—for example, placing the wolf's jumping attack origin slightly above the body center.
Base Class + Subclass Override Pattern: This is a typical "data-driven design" in UE. BP_Wolf and BP_Snake inherit from BP_AnimalBase and only modify default values without changing logic, achieving behavioral diversity while maintaining a single code implementation and making it easy to fix bugs uniformly in the future.
BeginPlay Initialization and Future Plans
In BeginPlay, the developer first checks HasAuthority to ensure initialization only executes on the server, then sets CurrentHealth to MaxHealth, applies WalkSpeed via SetMovementMaxSpeed, and sets AnimalState to Idle.
The developer mentioned that this video completes the "enemy on paper"—no visual representation, only a logical skeleton. The next stage will implement the damage structure and hook up behavior trees to drive the AI's actual movement and behavior switching.
From an architectural perspective, this design has two ideas worth learning from: first, the universality of interfaces—the damage interface isn't bound to specific Actor types, so both players and enemies can reuse it; second, the base class variables reserve enough room for differentiation, letting subclasses define completely different animal behaviors just by overriding parameters. For developers currently building Unreal AI systems, this "interfaces before implementation, base class before subclass" approach is worth referencing.
The Role of HasAuthority: HasAuthority determines whether the current execution context has network authority (i.e., whether it's the server). In multiplayer games, core data like health and state machines must be initialized by the server; executing on the client would produce state divergence. This is a fundamental rule of UE network synchronization.
The Meaning of SetMovementMaxSpeed: This function sets the CharacterMovementComponent's maximum walking speed, and it's where the WalkSpeed variable actually takes effect. Distinguishing Walk and Run speeds is a common practice—AI uses WalkSpeed during Roaming and switches to RunSpeed during Chasing.
How Behavior Trees Connect: In the next stage, the behavior tree will be mounted via AIController, with Blackboard Keys bound to variables like AnimalState and TargetActor. BTService will periodically update perception data, and BTTask will execute movement and attacks. The overall architecture will become a four-layer combination of "enum + interface + base class + behavior tree," which is also the standard AI paradigm recommended by Unreal officially.
One-line Summary
A complete breakdown of upfront design for Unreal animal AI architecture, from state enums and Blueprint interfaces to base class variables.
Paragraph Summary
The article breaks down the upfront architectural work of building an animal AI system in Unreal by an overseas developer, centered on three layers: state management, interface abstraction, and base class variables. The state enum E_AnimalState defines seven behaviors—Idle, Roaming, Investigating, Chasing, Attacking, Fleeing, and Death—covering the complete chain from patrol to escape. At the interface level, BPI_Damageable implements universal damage reception and reception checks, reusable for player characters; BPI_AnimalTarget implements animal-specific target validity, position, and threat level queries, with IsValidAnimalTarget performing pre-filtering before damage checks to handle scenarios like the player being knocked down or invincible. The base class BP_AnimalBase inherits from Character, with variables organized into five groups: basic info, movement, detection, combat, and behavior. The detection distance design reserves room for subclass differentiation and overriding. In BeginPlay, HasAuthority ensures initialization only on the server, and the next stage will connect behavior trees to drive actual behavior.
Related articles

Python 3.15 New Feature: Is the sentinel Type Better Than None?
Python 3.15 adds the sentinel type, using named unique sentinel objects to replace None and bare object(), resolving confusion among missing values, explicit emptiness, and invalid input while avoiding type hint failures.

Deep Learning's Three Architectures and the Universal Approximation Theorem: A Complete Guide to MLPs, CNNs, and Transformers
Explaining the inductive bias differences among MLP, CNN, and Transformer, the existence meaning of the Universal Approximation Theorem (UAT), and the role of Taylor expansion in approximation analysis, while clearing up common misconceptions.

GitLab Emergency Patch Release: Analysis of Critical Security Fixes
GitLab releases critical patch 19.5.1, sparking 355 points of discussion on Hacker News. This article analyzes the background, upgrade steps for self-hosted instances, and verification points to help DevOps teams respond quickly to security updates.