Simple AI Behaviors: Following and Avoiding

Now that you understand state machines and decision trees, let's put that knowledge into practice by creating simple, effective AI behaviors. In this chapter, you'll learn how to make characters follow targets and avoid obstacles - two of the most common AI behaviors in games.

What You'll Learn

By the end of this chapter, you'll be able to:

  • Implement following behavior for AI characters
  • Create obstacle avoidance systems
  • Combine following and avoiding for realistic movement
  • Optimize these behaviors for performance

Following Behavior: The Basics

Following behavior makes an AI character move toward a target. It's used for enemies chasing players, NPCs following leaders, or creatures tracking food. The core concept is simple: calculate the direction to the target and move in that direction.

Simple Following in Unity

Here's a basic following implementation:

public class FollowBehavior : MonoBehaviour
{
    public Transform target;
    public float speed = 5f;
    public float stoppingDistance = 2f;

    void Update()
    {
        if (target == null) return;

        // Calculate distance to target
        float distance = Vector3.Distance(transform.position, target.position);

        // Only move if not too close
        if (distance > stoppingDistance)
        {
            // Calculate direction to target
            Vector3 direction = (target.position - transform.position).normalized;

            // Move towards target
            transform.position += direction * speed * Time.deltaTime;

            // Optional: Rotate to face target
            transform.LookAt(target);
        }
    }
}

Following with Smooth Rotation

For more natural movement, add smooth rotation:

public class SmoothFollowBehavior : MonoBehaviour
{
    public Transform target;
    public float moveSpeed = 5f;
    public float rotationSpeed = 5f;
    public float stoppingDistance = 2f;

    void Update()
    {
        if (target == null) return;

        float distance = Vector3.Distance(transform.position, target.position);

        if (distance > stoppingDistance)
        {
            // Calculate direction
            Vector3 direction = (target.position - transform.position).normalized;

            // Smooth rotation
            Quaternion lookRotation = Quaternion.LookRotation(direction);
            transform.rotation = Quaternion.Slerp(
                transform.rotation, 
                lookRotation, 
                rotationSpeed * Time.deltaTime
            );

            // Move forward
            transform.position += transform.forward * moveSpeed * Time.deltaTime;
        }
    }
}

Following in Godot

Here's the same behavior in GDScript:

extends CharacterBody2D

@export var target: Node2D
@export var speed: float = 200.0
@export var stopping_distance: float = 50.0

func _physics_process(delta):
    if target == null:
        return

    var distance = global_position.distance_to(target.global_position)

    if distance > stopping_distance:
        var direction = (target.global_position - global_position).normalized()
        velocity = direction * speed
        move_and_slide()

        # Rotate to face target
        look_at(target.global_position)

Obstacle Avoidance: The Basics

Obstacle avoidance prevents AI characters from walking into walls, objects, or other characters. It uses raycasting or collision detection to detect obstacles and steer around them.

Simple Obstacle Avoidance in Unity

Here's a basic avoidance system using raycasting:

public class AvoidObstacles : MonoBehaviour
{
    public float avoidanceDistance = 5f;
    public float avoidanceForce = 10f;
    public LayerMask obstacleLayer;

    void Update()
    {
        Vector3 avoidanceDirection = Vector3.zero;

        // Cast rays in multiple directions
        Vector3[] rayDirections = {
            transform.forward,
            transform.forward + transform.right,
            transform.forward - transform.right,
            transform.right,
            -transform.right
        };

        foreach (Vector3 direction in rayDirections)
        {
            RaycastHit hit;
            if (Physics.Raycast(transform.position, direction, out hit, avoidanceDistance, obstacleLayer))
            {
                // Calculate avoidance direction (away from obstacle)
                Vector3 avoidDir = (transform.position - hit.point).normalized;
                avoidanceDirection += avoidDir;
            }
        }

        // Apply avoidance force
        if (avoidanceDirection != Vector3.zero)
        {
            avoidanceDirection.Normalize();
            transform.position += avoidanceDirection * avoidanceForce * Time.deltaTime;
        }
    }
}

Advanced Avoidance with Steering

For smoother avoidance, use steering forces:

public class SteeringAvoidance : MonoBehaviour
{
    public float avoidanceRadius = 3f;
    public float avoidanceWeight = 2f;
    public LayerMask obstacleLayer;

    private Vector3 currentVelocity;
    public float maxSpeed = 5f;
    public float maxForce = 10f;

    void Update()
    {
        Vector3 avoidanceForce = CalculateAvoidanceForce();
        Vector3 steering = Vector3.ClampMagnitude(avoidanceForce * avoidanceWeight, maxForce);

        currentVelocity = Vector3.ClampMagnitude(currentVelocity + steering, maxSpeed);
        transform.position += currentVelocity * Time.deltaTime;
    }

    Vector3 CalculateAvoidanceForce()
    {
        Collider[] obstacles = Physics.OverlapSphere(transform.position, avoidanceRadius, obstacleLayer);
        Vector3 avoidanceForce = Vector3.zero;

        foreach (Collider obstacle in obstacles)
        {
            Vector3 directionAway = (transform.position - obstacle.transform.position).normalized;
            float distance = Vector3.Distance(transform.position, obstacle.transform.position);
            float strength = 1f - (distance / avoidanceRadius);

            avoidanceForce += directionAway * strength;
        }

        return avoidanceForce.normalized;
    }
}

Combining Following and Avoiding

The real power comes from combining both behaviors. Here's how to make an AI that follows a target while avoiding obstacles:

public class FollowAndAvoid : MonoBehaviour
{
    public Transform target;
    public float followSpeed = 5f;
    public float avoidanceRadius = 3f;
    public float avoidanceWeight = 2f;
    public float stoppingDistance = 2f;
    public LayerMask obstacleLayer;

    void Update()
    {
        if (target == null) return;

        Vector3 followDirection = CalculateFollowDirection();
        Vector3 avoidanceDirection = CalculateAvoidanceDirection();

        // Combine directions (avoidance has priority)
        Vector3 finalDirection = (followDirection + avoidanceDirection * avoidanceWeight).normalized;

        // Move
        float distance = Vector3.Distance(transform.position, target.position);
        if (distance > stoppingDistance)
        {
            transform.position += finalDirection * followSpeed * Time.deltaTime;
            transform.LookAt(transform.position + finalDirection);
        }
    }

    Vector3 CalculateFollowDirection()
    {
        return (target.position - transform.position).normalized;
    }

    Vector3 CalculateAvoidanceDirection()
    {
        Collider[] obstacles = Physics.OverlapSphere(transform.position, avoidanceRadius, obstacleLayer);
        Vector3 avoidance = Vector3.zero;

        foreach (Collider obstacle in obstacles)
        {
            Vector3 directionAway = (transform.position - obstacle.transform.position).normalized;
            float distance = Vector3.Distance(transform.position, obstacle.transform.position);
            float strength = 1f - (distance / avoidanceRadius);

            avoidance += directionAway * strength;
        }

        return avoidance.normalized;
    }
}

Pro Tips for Simple AI Behaviors

Performance Optimization

  • Use object pooling for frequently created/destroyed AI
  • Limit raycast frequency (don't cast every frame if not needed)
  • Use spatial partitioning for obstacle detection
  • Cache frequently accessed values (like target position)

Making Behaviors Feel Natural

  • Add slight randomness to movement speed
  • Use smooth interpolation for rotation
  • Add acceleration and deceleration
  • Consider adding "personality" through speed variations

Common Mistakes to Avoid

  • Don't update every frame if the target isn't moving
  • Don't forget to normalize direction vectors
  • Don't make avoidance too aggressive (creates jittery movement)
  • Don't ignore performance with too many raycasts

Mini Challenge: Create a Following Enemy

Try creating an enemy that:

  1. Follows the player when within detection range
  2. Avoids walls and obstacles while following
  3. Stops at a safe distance before attacking
  4. Smoothly rotates to face the player

Use the code examples above as a starting point, and experiment with different speeds, distances, and avoidance weights.

Troubleshooting Common Issues

AI Gets Stuck on Obstacles

  • Increase avoidance radius
  • Add multiple raycast directions
  • Use sphere casting instead of raycasting
  • Add a "backing up" behavior when stuck

AI Moves Too Jerkily

  • Smooth the avoidance direction over time
  • Reduce avoidance weight
  • Add movement smoothing/damping
  • Use steering forces instead of direct position changes

AI Doesn't Follow Properly

  • Check that target reference is set
  • Verify distance calculations
  • Ensure movement speed is appropriate
  • Check for conflicting movement scripts

What's Next?

You've learned how to create basic following and avoiding behaviors. In the next chapter, you'll discover how to use AI tools to generate game assets like sprites, textures, and music - expanding your toolkit for game development.

Resources

Community Support

  • Discord Server: Get help with AI behavior implementation
  • GitHub Repository: Share your following/avoiding code
  • AI Game Development Forums: Learn from other developers
  • Course Discussion: Share your progress and get feedback

Ready to learn how AI can help create game assets? Continue to Chapter 5: AI Asset Generation: Sprites, Textures, and Music and discover how to use AI tools for content creation.