Adding AI NPCs in PlayCanvas

Updated June 2026
Non-player characters (NPCs) with believable behavior transform a static 3D scene into a living game world. PlayCanvas provides the scripting framework, physics raycasting, and event systems you need to build NPCs that patrol areas, detect the player, give chase, attack, and coordinate with each other. This guide walks you through implementing game AI from basic state machines to multi-NPC coordination.

Game AI does not need to be complex to be effective. Most convincing NPC behavior comes from a small set of well-tuned states with clear transitions between them. A guard that idles at a post, patrols between waypoints, investigates sounds, chases intruders, and returns to post when the threat is lost feels intelligent to the player even though each individual behavior is simple. The key is making the transitions between states responsive and the behaviors within each state varied enough to avoid obvious repetition.

Design an NPC State Machine

A finite state machine (FSM) is the most practical architecture for game NPC behavior. Each state represents a behavior mode: idle, patrol, alert, chase, attack, flee, or return. The NPC is always in exactly one state, and transitions between states are triggered by conditions you define, like "player detected within 20 meters" or "health below 25 percent."

Implement the FSM in a PlayCanvas script by storing the current state as a string or enum variable. In the update method, use a switch or if-else chain to execute the behavior for the current state. Each state's logic checks its transition conditions first, switches state if a condition is met, and otherwise executes the state's ongoing behavior. Keep the state-checking logic separate from the behavior logic so you can modify transitions without rewriting movement code.

A basic NPC FSM might have five states. The "idle" state plays a standing animation and periodically checks if the player is nearby. The "patrol" state moves the NPC between waypoints on a defined route. The "chase" state moves toward the player's last known position. The "attack" state plays an attack animation and applies damage when the player is within melee or projectile range. The "return" state navigates the NPC back to its patrol route after losing sight of the player.

Add hysteresis to your transition conditions to prevent rapid flickering between states. If the NPC transitions to "chase" when the player is closer than 15 meters, set the "return to patrol" threshold at 25 meters rather than 15. This gap prevents the NPC from switching between chase and patrol every frame when the player hovers near the detection boundary. You can also add minimum time requirements for states, ensuring the NPC stays in a state for at least a second before evaluating transitions.

Implement a Vision and Awareness System

NPCs need sensory input to make decisions. The most common sense for game AI is vision: can the NPC see the player? A convincing vision system checks three conditions: distance (is the player close enough?), angle (is the player within the NPC's field of view?), and line of sight (is there an unobstructed path between the NPC and the player?).

Distance checking is straightforward. Calculate the vector from the NPC to the player using player.getPosition().clone().sub(this.entity.getPosition()) and check its length against a detection radius. This is cheap to compute and should be the first check, skipping the more expensive angle and raycast checks when the player is out of range entirely.

Angle checking compares the NPC's forward direction with the direction toward the player. Use the dot product between the NPC's forward vector and the normalized direction-to-player vector. A dot product of 1 means the player is directly ahead, 0 means 90 degrees to the side, and -1 means directly behind. For a 120-degree field of view (60 degrees on each side of center), accept dot products greater than 0.5. Adjusting this threshold creates NPCs with wide peripheral awareness or narrow tunnel vision.

Line-of-sight checking uses physics raycasting to verify nothing blocks the view. Cast a ray from the NPC's eye position (typically the entity's position offset upward to head height) toward the player's position. If the raycast hits the player entity, the NPC has clear line of sight. If it hits a wall, obstacle, or terrain first, the view is blocked. Use the raycastFirst method for efficiency since you only need the closest intersection.

Trigger volumes provide a complementary awareness system. Place a large sphere trigger around each NPC that represents its hearing range. When the player enters this trigger, the NPC becomes "alert," increasing its patrol vigilance or turning toward the sound source. This lets NPCs respond to the player's presence before achieving visual contact, creating a more convincing awareness progression from oblivious to alert to fully engaged.

Build Patrol and Navigation Behaviors

Patrol behavior moves an NPC along a predefined path when no threat is present. The simplest implementation uses a list of waypoint positions that the NPC visits in sequence. Create empty entities in the editor to mark waypoint positions, add them as script attributes on the NPC's AI script, and iterate through the list during the patrol state.

Movement toward a waypoint uses vector math in the update loop. Calculate the direction from the NPC to the current target waypoint, normalize it, multiply by the movement speed and delta time, and apply the result as a position offset. When the NPC arrives within a threshold distance of the waypoint (typically 0.5 to 1 meter), advance to the next waypoint in the list. Loop back to the first waypoint after reaching the last one for a circular patrol, or reverse direction for a back-and-forth pattern.

Smooth turning prevents NPCs from instantly snapping to face their movement direction. Instead of setting the NPC's rotation directly, interpolate between the current facing direction and the desired direction using a lerp or slerp function. A turn speed of 3 to 5 radians per second produces natural-looking rotation for humanoid characters. Faster turn speeds work for alert or panicked NPCs, while slower values suit casual or relaxed patrol behavior.

Add variation to patrol behavior so NPCs do not look robotic. Randomize the pause duration at each waypoint between 1 and 4 seconds. Vary movement speed slightly within a range. Play idle animations like looking around or adjusting equipment during waypoint pauses. These small variations break the mechanical repetition that makes AI feel artificial. You can also randomly skip waypoints or choose between multiple patrol routes to keep the NPC's movement pattern less predictable.

For more complex environments, consider implementing a navigation mesh (navmesh) system. While PlayCanvas does not include a built-in navmesh solution, community libraries and custom implementations provide pathfinding on pre-computed navigation meshes. A navmesh defines walkable surfaces as connected polygons, and A* pathfinding calculates optimal routes between any two points on the mesh, automatically navigating around obstacles, through doorways, and up ramps.

Add Chase and Combat Logic

When the vision system detects the player, the NPC transitions to a chase state. Chase behavior is similar to patrol movement but targets the player's current position instead of a fixed waypoint. Update the target position every frame so the NPC tracks the player's movement. Apply the same directional movement and smooth turning as the patrol state, but typically at a higher speed to create tension.

Store the player's last known position when the NPC loses line of sight. Instead of immediately giving up, have the NPC continue moving toward the last known position. When it arrives and still cannot see the player, transition to a "search" or "return" state. This creates the realistic behavior of an NPC investigating where the player was last seen rather than instantly losing interest when the player ducks behind cover.

Attack behavior activates when the player is within the NPC's attack range. For melee combat, check the distance to the player against a range value (typically 1.5 to 3 meters). When in range, play the attack animation and apply damage at a specific frame in the animation using animation events. Add a cooldown timer between attacks so the NPC does not strike every frame, which both looks natural and gives the player time to react.

For ranged NPCs, the attack state involves aiming at the player and spawning projectile entities. Create the projectile as a template entity with a rigidbody, collision shape, and movement script. Instantiate it at the NPC's weapon position, set its velocity toward the player (with optional leading for moving targets), and let the physics system handle the rest. Alternatively, use raycasting for instant-hit ranged attacks, checking line of sight and applying damage immediately on the ray hit.

Flee behavior reverses the chase logic. Calculate the direction away from the player and move in that direction. NPCs might flee when their health drops below a threshold, when they are outnumbered, or when a specific game event triggers retreat. Add pathfinding awareness to flee behavior so the NPC runs toward cover or allies rather than blindly away from the player into a dead end.

Coordinate Multiple NPCs

Individual NPC intelligence becomes more convincing when multiple NPCs coordinate. A manager script, attached to an empty "AI Manager" entity, maintains a shared state that all NPCs can read. This shared state might include the player's last known position, an alert level for the area, a list of active NPCs and their current states, and communication events that propagate information between NPCs.

When one NPC spots the player, it fires an event through the AI manager. Other NPCs within communication range receive this event and update their own awareness, transitioning from patrol to alert or chase without individually spotting the player themselves. This creates the effect of NPCs calling out to each other and coordinating a response, which feels much more intelligent than each NPC operating in isolation.

Flanking behavior uses the manager to prevent all NPCs from running directly at the player from the same angle. The manager assigns approach angles to each pursuing NPC, spreading them around the player's position. One NPC approaches from the front while others circle to the sides or behind. Implement this by offsetting each NPC's target position from the player by a direction vector rotated by their assigned angle.

Group formation is useful for patrolling squads. The manager defines formation positions relative to a leader entity, and follower NPCs maintain their formation offset while the leader follows the patrol route. When combat starts, the formation breaks and NPCs switch to individual combat behaviors. When combat ends, they reform around the leader and resume patrol.

Limit the number of NPCs that actively engage the player simultaneously. In many games, having more than 3 to 4 melee attackers surrounding the player at once feels unfair and visually cluttered. The manager can queue NPCs for engagement, letting some circle at medium range while waiting for their turn to attack. This creates natural-looking combat where NPCs take turns rather than all piling on at once.

Key Takeaway

Start with a simple finite state machine for each NPC, add a vision system built on raycasting and trigger volumes, and use a manager script to coordinate group behavior. Simple states with well-tuned transitions produce NPCs that feel smart without requiring complex AI algorithms.