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:
- Detection Strategy — how candidates are found (trigger collider, raycast, proxy, reference list, …).
- Filter chain — which candidates are kept. Filters can also rewrite the candidate (e.g. a child collider rewrites to its parent's AttachableObject).
- 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.
- Create a GameObject named PickupZone. Add a Box Collider, check Is Trigger, and scale it to the area you want to cover.
- Add a Detector component (Add Component → Jungle → Reactions → Detector).
- 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.
- 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.
- Create a GameObject named CursorDetector (or use one of your existing agent objects).
- Add a Detector component.
- Detection Strategy — pick Raycast Detection Strategy (or the camera-mouse-raycast variant). Configure the camera reference and the layer mask.
- Filters —
Is 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 (raisingOnItemRemoved) 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¶
- Reactor tutorial — react to detector changes.
- AttachingAgent tutorial — the prime detector consumer in Octoputs.
- Detector reference — full property list.