Tutorial: AttachingAgent Workflow¶
Automate the grab-hold-drop cycle without continuous player input — a robot arm picks items off a conveyor and places them on shelves, a delivery drone moves cargo between stations, an NPC carries objects between rooms. A single component owns the whole workflow.
By the end of this tutorial you'll have an agent that grabs from a source detector, holds the item at a configurable point, then drops it at the best available destination — running once, or on autopilot.
Prerequisites: Octoputs installed (Installation). At least one AttachableObject and a handful of AttachmentPoint slots in the scene. Working knowledge from Your First Drag and Drop helps but isn't required — the agent owns most of the wiring.
1. Create the Agent¶
Create an empty GameObject named Agent.
Add the AttachingAgent component.
Add Component → Octoputs → Transfer → Attaching Agent
The Inspector shows seven sections: Grab Trigger, Grab, Holding, Drop Trigger, Drop Destination, Automation, Events. We'll walk through each.
2. Holding Point — Required¶
The agent always needs a place to keep the attachable between grab and drop, even if it spends only a frame there.
Create a child of Agent named HoldPoint. Add an AttachmentPoint component to it. Position it where you want held objects to appear — at the tip of a robot gripper, above an NPC's head, on a delivery tray.
Drag HoldPoint into the agent's Holding Point field.
Mandatory
The Holding Point is required. The agent shows a validation warning if it's empty.
The default AttachmentPoint configuration handles the snap-to-position on grab, so the held object will simply appear at the HoldPoint. To animate the grab (e.g. a finger close), customize HoldPoint's Attaching process — see Transform Operations.
3. Wire the Grab Source¶
The Grab section answers what to pick up.
- Grab Source is a SmartAttachableObject — it can be a direct reference, a list, or a dynamic source resolved through any
IGameObjectValue. By default it's set to Dynamic mode, which is what you want for "pick from whatever a detector says is in range".
The typical setup:
- Add a separate Detector GameObject somewhere in the scene — for example a child of the agent with a trigger collider as its detection strategy.
- Configure the Detector to find Attachables: detection strategy = Trigger Volume (or Raycast / Reference List), filters =
IsAttachable, plus any other criteria you need. - On the agent, in Grab Source, set the Source Object to
GameObject From Detectorand drag the Detector into it. - (Optional) Set the detector's selection mode (First / Last / Random) to control which detected attachable wins when there are several.
You now have a fully dynamic source — the agent always grabs whatever the detector is reporting right now.
Static or hand-authored sources
Switch the SmartAttachableObject to Local mode and drag a single attachable in for a fixed source. Switch to Multiple Values to author an array. The agent treats all three modes interchangeably.
Grab Filters¶
Checks the candidate must pass in addition to whatever the detector already enforces. Useful for agent-specific rules: "only grab heavy items" while the detector itself just finds attachables. The candidate is already a resolved attachable here, so add checks like AttachableTagCheck, HeldStateCheck directly — no umbrella wrapper. (Need a generic GameObject filter instead? Add the Object Filter check.)
Instant Detach Source¶
When enabled, the source's Detach is skipped — the attachable is yanked off its current point immediately. Use for fast tools that shouldn't wait for animations. Disabled by default.
4. Wire the Drop Destination¶
Mirror image of the grab source.
- Drop Destination is a SmartAttachmentPoint. Configure it the same way — Dynamic with
GameObject From Detectoron a destination-side Detector, or Local for a fixed slot.
When the agent attempts a drop:
- It walks the candidates from the SmartAttachmentPoint.
- For each candidate, it asks the point: "can you currently accept this attachable?" (the point's own filters + conditions).
- Then it checks the agent's own Drop Filters.
- The first candidate that passes both is the chosen destination.
If no candidate passes:
- Detach If No Destination = true → the agent releases the object in place (it simply falls / sits).
- Detach If No Destination = false → the agent re-attaches the object to the holding point and stays in the Holding state.
Drop-On-Zone Process¶
The optional Drop On Zone Process runs after the attachable lands on a destination point. Use it for a quick post-drop animation, sound, or effect.
No-Destination Detach Process¶
If DetachIfNoDestination is true, the optional No Destination Detach Process runs when the agent gives up and lets go in place. Use it to fire a "released" effect.
5. Wire Triggers¶
Now decide when the agent grabs and drops.
Grab Trigger¶
- Grab Event — an
IEvent. Pick anything from the picker:
| Event | Use when |
|---|---|
MouseButtonEvent |
Player clicks. |
InputSystemActionEvent |
Bound to a new-input-system action. |
InputButtonEvent |
Legacy Input Manager button. |
DurationEvent |
Fires every N seconds — turns the agent into a metronome. |
SignalEventFromHub |
Listens to a SignalType on a LocalSignalTransmitter. |
EventFromAsset |
Listens to a shared EventAsset. |
For automation (conveyor sorter, NPC routine), DurationEvent is the simplest starting point.
- Grab Conditions — extra gates. All must pass for the grab to proceed. For example, "only during the work shift", "only while the battery isn't empty".
Drop Trigger¶
- Drop Event — same picker. If you leave Drop Event empty, the grab event toggles — one click grabs, next click drops. That's the cleanest setup for player-driven agents.
Set a different event here for two-button workflows (click to grab, right-click to drop).
- Drop Conditions — additional gates before a drop attempt.
Preparation Processes¶
Each side has a Preparation Process that runs before the actual attach/detach:
- Grab Preparation Process — e.g. a "reach toward source" animation. The agent waits for it to finish.
- Drop Preparation Process — e.g. an "extend toward destination" animation.
Leave empty for instant grab/drop.
6. Automation¶
Two toggles that turn the agent into an autonomous worker.
- Auto Repeat — once a drop finishes, the agent immediately tries another grab. The loop runs until the source is empty or every destination rejects.
- Buffer Requests — grab/drop events arriving in the wrong state get remembered and replayed when the agent reaches the appropriate state. Without buffering, an event arriving while busy is silently dropped.
Pair both for a robust "click ahead" feel on player-driven agents, or just Auto Repeat alone for fully autonomous ones.
7. Test the Loop¶
Press Play and fire the grab event:
- The agent picks an eligible attachable from the Grab Source.
- Grab Preparation runs (if configured).
- The attachable detaches from its current point (instant or sequenced).
- It attaches to HoldPoint. Agent state → Holding.
Fire the drop event (or the grab event again in toggle mode):
- Drop Preparation runs.
- The attachable detaches from HoldPoint.
- The agent walks its destination candidates and attaches to the first that accepts — or detaches in place if none does.
- Drop-On-Zone Process (or No-Destination Detach Process) runs.
- Agent state → Idle.
If a grab or drop is rejected, the agent records a structured rejection (LastRejection, LastRejectionDetail, plus per-candidate verdicts for drop failures). Open the agent's Debug panel in the Inspector to inspect why a drop went sideways — e.g. "All 3 candidate points blocked by their own CanAttach (already holding)".
8. Agent Lifecycle Reference¶
stateDiagram-v2
[*] --> Idle
Idle --> PreparingGrab : Grab event accepted
PreparingGrab --> Grabbing : Preparation complete
Grabbing --> Holding : Attachable lands on HoldPoint
Holding --> PreparingDrop : Drop event accepted
PreparingDrop --> Dropping : Preparation complete
Dropping --> Idle : Placed or released
State probes:
| Property | Meaning |
|---|---|
IsIdle / IsPreparingGrab / IsGrabbing / IsHolding / IsPreparingDrop / IsDropping |
Each true exactly when the agent is in that state. |
CurrentAttachable |
The attachable in flight (null when idle). |
LastDropDestination |
The point used by the most recent successful drop. |
Counters / diagnostics:
| Property | Meaning |
|---|---|
GrabAttempts / GrabSuccesses |
Lifetime grab counters. |
DropAttempts / DropSuccesses |
Lifetime drop counters. |
LastRejection / LastRejectionDetail / LastRejectionTime |
Most recent failure. |
TryGetRejection(int) |
Walk the recent-rejection ring buffer (capacity 8). |
UnityEvents fire at key transitions: OnGrabStarted, OnGrabComplete, OnDropStarted, OnDropComplete. Wire UI, audio, particles directly.
9. Practical Example: Conveyor Sorter¶
Scene hierarchy:
RobotArm (AttachingAgent)
├─ HoldPoint (AttachmentPoint)
├─ SourceDetector (Detector — Trigger Volume, IsAttachable filter)
└─ DestDetector (Detector — Reference List of shelf slots, IsAttachmentPoint filter)
Shelves
├─ Shelf1 (AttachmentPoint)
├─ Shelf2 (AttachmentPoint)
└─ Shelf3 (AttachmentPoint)
Items (spawned by a conveyor producer)
├─ Box1 (AttachableObject)
└─ ...
Agent configuration:
| Section | Field | Value |
|---|---|---|
| Grab Trigger | Grab Event | DurationEvent (every 3s) |
| Grab | Grab Source | SmartAttachableObject → Dynamic → GameObjectFromDetector(SourceDetector) |
| Holding | Holding Point | HoldPoint |
| Drop Trigger | Drop Event | (empty — toggles with grab) |
| Drop Destination | Drop Destination | SmartAttachmentPoint → Dynamic → GameObjectFromDetector(DestDetector) |
| Drop Destination | Detach If No Destination | false (keep holding when shelves full) |
| Automation | Auto Repeat | true |
The arm grabs the first box detected on the conveyor and immediately drops it into the first available shelf. When shelves fill up, the arm keeps holding rather than dumping the box in place.
Animate the arm by setting the Grab Preparation Process to a "reach toward source" animation and Drop Preparation Process to a "reach toward destination" animation — Octoputs ships with transform operations that can drive the arm's parts directly.
Next Steps¶
- Add tag-based picky behaviour with Tag-Based Filtering.
- Make the grab/drop motion expressive with Transform Operations.
- Constrain the agent's working area with a Constrainer.
- Browse every component in the API Reference.