# Architecture Reference

***

## Component Overview

```
AIBehavior (MonoBehaviour) — GOAP brain
  ├── GoalArbiter              — selects highest-priority achievable goal
  ├── Planner (A* search)      — finds cheapest action sequence for a goal
  │     ├── MinHeap            — O(log n) open list
  │     ├── PlannerNode pool   — reduces GC allocations
  │     ├── State pool         — reuses flat float[] arrays between searches
  │     └── Plan cache         — instant replay for repeated state+goal combos
  ├── State (States)           — behavior-local key-value state with change events
  └── Actions []               — pool of Action subclasses available for planning
        └── ResolveTarget()    — queries TargetBinderRegistry; locks winner, auto-releases on completion

AIAgent (MonoBehaviour) — navigation/movement body
  └── NavMeshAgent             — Unity pathfinding; owns Target, TargetTransform, IsTargetReached

Sensor (MonoBehaviour, abstract) — environment perception
  ├── RangeSensor              — detects objects in a sphere (Physics.OverlapSphere or TargetBinderRegistry)
  └── LineOfSightSensor        — sphere + optional FOV cone + Physics.Linecast obstruction check

WorldStatesRegistry (static)
  └── Categories (States)      — named shared state sets, subscribed to by AIBehaviors

EngineData (ScriptableObject, in Resources/)
  └── AutoRegisterWorldStates() — registers all WorldStates categories before scene load

TargetBinderRegistry (static)
  └── TargetBinder[]           — all active scene binders (self-register on enable/disable)
```

***

## Class Hierarchy — Effects

```
Pair            key + value (base)
  ├── Requirement        adds: ComparisonOperator
  ├── Goal               (no additions)
  └── Effect             adds: EffectMode (Set / Add / Minus)
        └── WorldEffect      adds: Category (target WorldStatesManager category)
```

***

## Planner Internals

The planner avoids GC allocations through several mechanisms:

| Mechanism                       | Purpose                                                                                                                                                                                                                                                                                                                    |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Flat `float[]` state arrays** | State is stored as a dense array indexed by a `string→int` key registry, not a `Dictionary`. All copies and comparisons are `O(keyCount)` array operations.                                                                                                                                                                |
| **NaN sentinel**                | Unset keys are represented as `float.NaN` in the flat array, avoiding sparse representation overhead.                                                                                                                                                                                                                      |
| **Node pool**                   | `PlannerNode` objects are pooled in a `Stack<PlannerNode>`. Nodes are reset and returned after each search.                                                                                                                                                                                                                |
| **State pool**                  | `float[]` arrays are pooled in a `Stack<float[]>`. Arrays too small for the current key count are replaced (rare after warm-up).                                                                                                                                                                                           |
| **Plan cache**                  | Up to 16 plans are cached by `(startStateHash, goalHash)`. Cache hits skip the A\* search entirely. Cache is invalidated when dynamic action costs change. On a hit, `BeginPlan` stores the matched `planKey` in `_cachedPlanKeyHit` so `StepPlan` retrieves the exact matching entry rather than the first non-null slot. |
| **Pre-indexed actions**         | At `BeginPlan()`, all actions are converted to `IndexedAction` structs (flat int indices, no dictionary lookups during search). Struct arrays are cached and only rebuilt when action count or the key registry grows; otherwise only costs are refreshed.                                                                 |
| **Admissible heuristic**        | Default h(n) = number of unsatisfied goal conditions. Never overestimates, so A\* is guaranteed optimal. Override via `AIBehavior.GoalEvaluator`.                                                                                                                                                                          |
| **`PlanStateContext`**          | Pre-allocated struct passed to `GoalEvaluator` at each node expansion. Zero heap allocation per heuristic call.                                                                                                                                                                                                            |
| **Async API**                   | `BeginPlan()` snapshots state on the main thread. `StepPlanAsync()` dispatches the A\* loop to a ThreadPool thread via `Task.Run()` — safe because `StepPlan` only accesses pre-indexed `float[]` arrays with no Unity API calls.                                                                                          |
| **Merged state dict**           | `BeginPlan()` and `AIBehavior.GetMergedCurrentState()` each reuse a single pre-allocated `Dictionary<string, float>` instance. No per-call allocations in the planning hot path.                                                                                                                                           |

***

## Public API — AIBehavior

| Member                     | Type                            | Description                                                                                                                |
| -------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `State`                    | `States`                        | Behavior's local state dictionary                                                                                          |
| `Name`                     | `string`                        | Name identifier for TargetBinder filtering. Defaults to `gameObject.name` when empty.                                      |
| `Group`                    | `string`                        | Group identifier used by `TargetBinder` filters                                                                            |
| `NavMeshAgent`             | `NavMeshAgent`                  | The pathfinding agent (delegates to `AIAgent`)                                                                             |
| `AIAgent`                  | `AIAgent`                       | The navigation/movement body component                                                                                     |
| `CurrentAction`            | `Action`                        | Currently executing action                                                                                                 |
| `Target`                   | `Transform`                     | Source Transform of the running action's navigation target. Null when idle or the action has no target.                    |
| `TargetPosition`           | `Vector3?`                      | World-space position the agent is navigating toward. Null when idle.                                                       |
| `Timer`                    | `float`                         | Time remaining on current action (mirrored from the running action's timer)                                                |
| `GoalArbiter`              | `GoalArbiter`                   | Goal selection and lifecycle                                                                                               |
| `GoalStacks`               | `List<GoalStack>`               | The agent's goal stacks (can be modified at runtime)                                                                       |
| `Actions`                  | `List<Action>`                  | Available actions                                                                                                          |
| `RepeatGoalStacks`         | `bool`                          | When true, restores all removable goal stacks and repeats the sequence after all goals are consumed                        |
| `CurrentPlan`              | `IReadOnlyList<IAction>`        | Read-only snapshot of the remaining action queue. Rebuilt on each access — suitable for editor display, not hot-path code. |
| `IsPlanning`               | `bool`                          | True while an async A\* search is running on a background thread                                                           |
| `BehaviorPreset`           | `BehaviorPreset`                | The preset asset loaded by this behavior, if any                                                                           |
| `BuildRelevantKeys()`      | `void`                          | Rebuilds the relevance key set from current goals and actions. Call after modifying goals or actions at runtime.           |
| `InvalidatePlannerCache()` | `void`                          | Forces the planner to discard all cached plans on the next cycle.                                                          |
| `GetAction<T>()`           | `Action`                        | Returns the first action of type `T` in the actions list, or null if not found.                                            |
| `OnStart`                  | `UnityEvent`                    | Fired in Start                                                                                                             |
| `OnPlanCreated`            | `UnityEvent`                    | Fired when a new plan is found                                                                                             |
| `OnPlanFailed`             | `UnityEvent`                    | Fired when planning fails or a plan is interrupted                                                                         |
| `OnPlanComplete`           | `UnityEvent`                    | Fired when the last action in a plan completes                                                                             |
| `OnActionStarted`          | `UnityEvent`                    | Fired when an action begins                                                                                                |
| `OnActionCompleted`        | `UnityEvent`                    | Fired when an action completes                                                                                             |
| `GoalEvaluator`            | `Func<PlanStateContext, float>` | Optional custom A\* scoring function. Runs on the background thread — do not access Unity APIs inside the delegate.        |

***

## Public API — AIAgent

| Member                       | Type           | Description                                                                                                                                   |
| ---------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `NavMeshAgent`               | `NavMeshAgent` | The Unity pathfinding agent (found in the parent hierarchy)                                                                                   |
| `Target`                     | `Transform`    | Source Transform of the current navigation target. Null when idle.                                                                            |
| `TargetPosition`             | `Vector3?`     | World-space position the agent is navigating toward. Null when idle.                                                                          |
| `IsTargetReached`            | `bool`         | True after the agent has arrived within `TargetReachSqrDistance` this action cycle                                                            |
| `TargetReachSqrDistance`     | `float`        | Squared reach threshold (`_targetReachDistance * _targetReachDistance`)                                                                       |
| `SetTarget(Transform, bool)` | `virtual void` | Sets a Transform as the nav destination. Pass `moveToTarget = false` to stop in place. No-op on `NavMeshAgent` when the component is missing. |
| `SetTarget(Vector3, bool)`   | `virtual void` | Sets a world-space position as the nav destination. No-op on `NavMeshAgent` when the component is missing.                                    |
| `ClearTarget()`              | `virtual void` | Clears the nav destination and resets arrival state. Stops the NavMeshAgent if present.                                                       |

***

## Public API — Action (subclass members)

| Member                            | Type                   | Description                                                                                                                              |
| --------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `Behavior`                        | `AIBehavior`           | Reference to the owning AIBehavior (set automatically)                                                                                   |
| `Agent`                           | `AIAgent`              | Reference to the owning AIAgent (set automatically)                                                                                      |
| `Target`                          | `Transform`            | Source Transform the action navigates toward. Null until resolved via `SelectBestBinder()` or Inspector assignment.                      |
| `TargetPosition`                  | `Vector3?`             | World-space position derived from `Target`. Null when `Target` is null.                                                                  |
| `SelectedBinder`                  | `TargetBinder`         | The TargetBinder chosen in the last `SelectBestBinder()` call, or null                                                                   |
| `Cost`                            | `float`                | Dynamic cost if set, otherwise static `_cost`                                                                                            |
| `IsRunning`                       | `bool`                 | True while the action is executing                                                                                                       |
| `IsIncludeOnPlanning`             | `bool`                 | When `false`, this action is excluded from planning. Shown grayed-out in the GOAP Graph Editor.                                          |
| `Name`                            | `string`               | Display name. Returns only the part before `[` when a plan-ordering DSL is present.                                                      |
| `TargetTag`                       | `string`               | Tag used to filter compatible TargetBinders. Must match a tag in EngineData → Target Tags. Empty = any binder.                           |
| `Parameters`                      | `List<Pair>`           | Named float parameters configured in the Inspector for this action instance                                                              |
| `_cost`                           | `float`                | A\* search cost (≥ 1, static)                                                                                                            |
| `_target`                         | `Transform`            | Static navigation target (Inspector-assignable). Used directly when set, bypassing TargetBinderRegistry.                                 |
| `_timer`                          | `float`                | Wait duration after reaching target                                                                                                      |
| `_requirements`                   | `List<Requirement>`    | Preconditions                                                                                                                            |
| `_effects`                        | `List<Effect>`         | Behavior state effects (each has a `Mode`: Set / Add / Minus, optional `Conditions`, and optional DSL `Expression`)                      |
| `_worldEffects`                   | `List<WorldEffect>`    | World state effects (each has a `Mode` and a `Category`)                                                                                 |
| `GetParameter(key, default)`      | `float`                | Returns the named parameter value, or `default` when the key is absent                                                                   |
| `HasParameter(key)`               | `bool`                 | Returns true when a parameter with `key` exists on this action instance                                                                  |
| `ComputeCost(behavior)`           | `virtual void`         | Called before each plan; override to set distance-based or context-based costs via `SetDynamicCost()`                                    |
| `SetDynamicCost(float)`           | `protected void`       | Sets a dynamic cost override (clamped to ≥ 0.01)                                                                                         |
| `ClearDynamicCost()`              | `protected void`       | Clears the dynamic cost; reverts `Cost` to `_cost`                                                                                       |
| `SelectBestBinder(bool isRandom)` | `virtual TargetBinder` | Queries `TargetBinderRegistry`; locks the nearest (or random) available binder matching `TargetTag`; sets `Target` and `SelectedBinder`. |
| `ReleaseBinder()`                 | `public void`          | Unlocks the held `TargetBinder` and clears the registry-sourced `_target`. Called automatically on completion and interrupt.             |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://beelabs-dev.gitbook.io/beelabs-docs/goap-engine/architecture-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
