Skip to content

Sensor Controller

The SensorController manages the lifecycle of all sensors attached to an agent. It polls each sensor at its configured interval and handles staggered timing to prevent CPU spikes.


How Sensors Work

Sensors are the primary data producers in the GOAP pipeline. They read world state (vision cones, proximity checks, waypoints, sound) and write results to the blackboard.

  1. Each sensor is a ScriptableObject (GoapSensorSO) defined on the Brain.
  2. The SensorController polls each sensor at its UpdateInterval (default 0.5s).
  3. First-tick timing is staggered using a deterministic offset based on the agent's InstanceID, preventing all agents from polling on the same frame.
  4. Sensor outputs are mapped to blackboard keys via the Brain's Key Manifest.

Warning

Sensors do not fire every frame. Any blackboard key written by a sensor may be up to one full interval old when read. Design all code that reads sensor-driven keys to tolerate stale data.


Output Declaration

Every sensor declares what it outputs using GetOutputs():

public override SensorOutputConfig[] GetOutputs() => new[]
{
    new SensorOutputConfig("TargetPosition", GoapKeyType.Vector3),
    new SensorOutputConfig("Found", GoapKeyType.Boolean),
};

Each output is a named slot with a data type. The GOAP Hub maps these output slots to concrete blackboard keys in the Key Manifest.

GoapKeyType

Type C# Type
Boolean bool
Float float
Vector3 Vector3
Integer int
Object GameObject
String string

Write Helpers

Sensors use typed write helpers that automatically handle temporal key routing:

// Simple writes (non-temporal)
WriteBool(settings, blackboard, "Found", true);
WriteFloat(settings, blackboard, "Distance", 12.5f);
WriteInt(settings, blackboard, "Count", 3);
WriteGameObject(settings, blackboard, "Target", targetGO);

// Vector3 write WITHOUT entity tracking
WriteVector3(settings, blackboard, "Position", pos);

// Vector3 write WITH entity tracking (for temporal/recollection keys)
WriteVector3(settings, blackboard, "Position", pos, targetGameObject);

Temporal Key Routing

The write helpers automatically check if a key is managed by the RecollectionSystem:

  • If the key is temporal, the helper calls ReportStimulus() instead of writing directly.
  • If the key is not temporal, the helper writes directly to the blackboard.

Tip

Always use WriteVector3 with the target parameter when writing position data for entities that should be tracked in memory. This enables confidence decay and multi-entity tracking.


Built-In Sensors

The framework ships with four sensors. Create them via Create > RGS > GOAP > Sensors > {name}.

Optical Sensor

Vision cone with line-of-sight raycast.

Output Type Description
Position Vector3 Target's world position
Found Bool Whether a valid target is within the vision cone
HasDirectSight Bool Whether a clear line of sight exists (raycast check)

Configurable: field of view angle, range, target layers, target tags, occlusion layers.

Auditory Sensor

Reads noise events from NoiseEmitter components.

Output Type Description
SoundPosition Vector3 Position of the detected noise

Pairs with the NoiseEmitter component on sound-producing GameObjects.

Sphere Sensor

Proximity detection using Physics.OverlapSphere.

Output Type Description
TargetPosition Vector3 Nearest valid target's position
TargetObject Object Reference to the nearest valid target
FoundTarget Bool Whether any valid target was detected

Configurable: radius, target layers, target tags.

Waypoint Sensor

Reads the current waypoint from WayPointManager.

Output Type Description
WaypointPosition Vector3 World position of the current waypoint
IsAtWaypoint Bool Whether the agent is within arrival distance

Pairs with the WayPointManager component for patrol routes.


NoiseEmitter

Attach NoiseEmitter to GameObjects that produce sound. The AuditorySensorSO reads emitted noise events.

public class NoiseEmitter : MonoBehaviour
{
    public void EmitNoise(NoiseType type);
    public void EmitNoise(NoiseType type, float radius);
}

SensorUtils

Utility class for target validation:

public static class SensorUtils
{
    // Validates a detected GameObject against layer mask and tag filters
    public static bool IsValidTarget(GameObject obj, LayerMask mask, string[] tags);
}

Sensor Timing Details

Setting Default Description Notes
UpdateInterval 0.5s How often the sensor fires Range: 0.1–2.0s. Lower = more responsive, higher CPU. See Performance Tuning.
Stagger offset Automatic First tick offset based on agent InstanceID Distributes sensor polls evenly across frames to prevent CPU spikes.

The staggering ensures that if you have 100 agents, their sensor polls are distributed evenly across the 0.5-second window rather than all firing on the same frame.

Tip

Tune intervals per-sensor based on importance. Vision sensors that drive state transitions may need 0.2s, while waypoint sensors can safely use 1.0s.


See Also

What's Next

  • Custom Sensors — Build your own sensor from scratch with a complete template.
  • Blackboard — Understand the key-value store that sensors write to.
  • Action Strategies — How strategies read sensor data from the blackboard.