Course contentsShow
← Unity Game Development
Lesson 558 of 8288. Artificial IntelligenceFree lesson

Scaling GOAP Systems for Multiple Agents

Refactor the planning architecture to handle multiple autonomous agents efficiently without overwhelming the main game thread.

In this lesson, you will learn how to offload heavy GOAP planning calculations to a background thread to prevent frame rate stutters when managing dozens of autonomous agents.

The Problem of Synchronous Planning

When you have a single agent using A* to search for an action plan, the impact on the Update() loop is negligible. However, if 50 agents request a new plan simultaneously, the main thread will stall while calculating state transitions and heuristic costs. To keep your game smooth, we must shift the "Planner" logic away from the Unity Main Thread.

Refactoring for Asynchronous Planning

Instead of calling Planner.Plan() directly within an agent’s logic, treat the Planner as a service that accepts a request and returns a result via a callback or a thread-safe task. Since Unity’s API (like Transform or GameObject) is not thread-safe, your planner must operate exclusively on data structures (POCOs) representing the world state.

Here is a simplified pattern for decoupling the planning process:

// Use a Task to run the planning logic off the main thread
public async void RequestPlanAsync(WorldState current, Goal goal) {
    // Planner operates on simple data, not GameObjects
    Plan newPlan = await Task.Run(() => {
        return planner.GeneratePlan(current, goal);
    });

    // Apply the resulting plan back on the main thread
    ApplyPlan(newPlan);
}

Managing Execution Load

Even with multi-threading, you shouldn't allow every agent to plan at the exact same millisecond. Implement a Priority Planner Queue. By using a simple Queue<Agent> system, you can restrict the system to process only 2–3 plans per frame. This throttles the workload and prevents the CPU from spiking, regardless of how many agents are currently "thinking."

Additionally, ensure your WorldState is cached. Instead of agents querying the live game scene during planning (which causes threading crashes), provide them with a "Snapshot" of the world taken at the moment the request was made.

Key Takeaway: By offloading pathfinding and state-graph searches to background threads using snapshot-based data, you decouple agent intelligence from the render loop, allowing for fluid performance at scale.