Skip to content

Tutorial: Sourcing GameObjects with Detector

Find GameObjects in the scene through triggers, raycasts, proxy lists — anything — and expose them through a single uniform interface (IItemSource<GameObject>). Hook the results into agents, reactors, transforms, UI. One picker, one filter chain, one event surface, every detection strategy.

By the end of this tutorial you'll have:

  • A trigger-volume Detector that finds Attachables in a zone.
  • A raycast-under-mouse Detector that picks whatever's under the cursor.
  • A Reactor that fires every time the detector gains its first item.

Prerequisites: Basic Unity scene with at least one GameObject you want to find.


What a Detector Is

A Detector is a ControllableComponent that exposes IItemSource<GameObject>. Three pluggable pieces:

  1. Detection Strategyhow candidates are found (trigger collider, raycast, proxy, reference list, …).
  2. Filter chainwhich candidates are kept. Filters can also rewrite the candidate (e.g. a child collider rewrites to its parent's AttachableObject).
  3. Reactive surface — UnityEvents (onNewAvailable, onNotAvailableAnymore, onNoMoreAvailable) and lifecycle processes (anyAvailableProcess, noneAvailableProcess, onAddedProcess, onRemovedProcess).

Detectors are pure read-only sources — they never mutate other containers as a side effect. To mirror detection into a container, drop a DetectorToContainerRelay next to the Detector.


1. Trigger Volume Detector

Goal: detect every Attachable that enters a tagged trigger.

  1. Create a GameObject named PickupZone. Add a Box Collider, check Is Trigger, and scale it to the area you want to cover.
  2. Add a Detector component (Add Component → Jungle → Reactions → Detector).
  3. Detection Strategy — pick Trigger Detection Strategy (or whatever the trigger-volume option is called). It reads from the colliders that enter/leave this GameObject's triggers.
  4. Filters — click + and add Is Attachable (or whatever filter limits to Attachables). Filter chains are AND-evaluated; add as many as you need.

Press Play and drag an AttachableObject into the trigger area. The detector's Available list now contains it. Move it out — the list empties.

Filter rewrites

A typed filter (e.g. AttachmentPointFilter) that finds the AttachmentPoint on a parent of the raw hit can rewrite the detected GameObject to the parent. The detector keeps the resolved GameObject — so consumers see the owner of the AttachmentPoint, not the child collider that triggered detection. The filter's lookup field controls this (Self / Parents / Children).


2. Raycast Under Mouse Detector

Goal: detect whichever Attachable is under the mouse cursor.

  1. Create a GameObject named CursorDetector (or use one of your existing agent objects).
  2. Add a Detector component.
  3. Detection Strategy — pick Raycast Detection Strategy (or the camera-mouse-raycast variant). Configure the camera reference and the layer mask.
  4. FiltersIs Attachable, same as before.

The detector now reports the current "thing under cursor" attachable as long as the strategy keeps casting (typically every frame).


3. Wire the Detector to a Consumer

A detector by itself just sits there reporting. To use it:

Feed an AttachingAgent

On an AttachingAgent, the Grab Source is a SmartAttachableObject. Set its mode to Dynamic and pick GameObject From Detector as the source object. Drag your Detector in. The agent now grabs whatever the detector reports.

Feed a Reactor

Add a Reactor. Pick a target that watches an IGameObjectValue source — set the source to GameObjectFromDetector(detector). The reactor fires when the detector gains its first item, runs while the detector is non-empty, completes when it becomes empty. Wire the body to whatever response you need.

Feed a UI element

A GameObjectFromDetector is also an IObservableGameObjectValue — bind a UI label to its current item, set a glow effect on the resolved GameObject's renderer, anything that takes a typed value source.


4. Detector Lifecycle Processes

The Detector has four optional processes that begin/end on detection edges:

Process Begins Ends
onAddedProcess Every add. Self-completes.
onRemovedProcess Every remove. Self-completes.
anyAvailableProcess Transition from 0 → 1 detected. When count drops back to 0.
noneAvailableProcess Transition from N → 0 detected. When a new item arrives.

Use anyAvailableProcess / noneAvailableProcess for "while items are present" / "while items are absent" effects (e.g. highlight a UI badge while the detector has something to pick up).

Use onAddedProcess / onRemovedProcess for "fire-and-forget on each edge" (e.g. a quick particle puff when an item enters).


5. Ignore-Until-Lost

A Detector exposes a useful tactical operation:

  • IgnoreUntilLost(GameObject) — marks an item as ignored. It's removed from the public available list (raising OnItemRemoved) and won't be re-surfaced until the detection strategy reports it has physically left detection range.

Used internally by Octoputs's transfer logic ("don't re-grab the thing I just dropped while it's still in my zone"). Wire it from your own logic if you need similar "lock this one out" behaviour.


6. Multiple Filters, Multiple Phases

A Detector can have many filters in the chain. Order matters when filters rewrite candidates — a rewrite happens at the filter that performs it, so later filters see the rewritten candidate.

Mix freely:

Detector
├─ Strategy: Trigger
└─ Filters:
   ├─ Is Attachable                  (also rewrites to Attachable's GameObject)
   ├─ Attachable Tag Filter (Red)
   └─ Attachable Eligibility Filter

This detector accepts only red-tagged Attachables that are currently eligible (not already attached somewhere blocking) and resolves the resulting GameObject to the Attachable owner.


7. Mirror to a Container

If you need a stateful container (an inventory list, a UI-bound list), drop a DetectorToContainerRelay on the same GameObject. The relay mirrors the detector's adds/removes into a configured IItemContainer<GameObject>. The detector remains pure; the relay does the side effect.


8. Detector vs Container vs Item Source

Three roles in the GameObject-routing world:

Role Read Write Lifecycle
Detector Yes (via IItemSource<GameObject>) No (pure source). Adds/removes driven by strategy.
Container (IItemContainer<GameObject>) Yes Yes (Take, Store, Remove). Adds/removes driven by callers.
Item Source (IItemSource<GameObject>) Yes No (read-only interface). Generic.

A Detector is an IItemSource. A container is both IItemSource and IItemContainer. Consumers that only need to read can target the source interface and accept either.


Next Steps