Skip to content

Tutorial: Tag-Based Filtering

Make red objects only fit red slots, and blue objects only fit blue slots. By the end of this tutorial, mismatched objects will be silently rejected — no code required.

Prerequisites: Complete Tutorial: Your First Drag and Drop, or have an equivalent scene with at least two AttachableObjects and two AttachmentPoints.


1. Starting Point

You should have a working scene with:

  • At least two movable objects (e.g. RedCube and BlueCube, each with an AttachableObject component).
  • At least two slots (e.g. RedSlot and BlueSlot, each with an AttachmentPoint component).
  • A way to attempt attaching them — the CursorAgent from the basic tutorial works, or any other agent / command setup.

If you only have one of each from the basic tutorial, duplicate them now and re-wire the agent's drop destination to a Detector that finds both slots, so the agent picks whichever is closer / first.


2. Create Color Tags

Tags are tiny label assets. They carry no logic; they're just identifiers that the filtering system matches against. Tags are shared Key assets. They live in Jungle Core, not Octoputs, so any system can use them. In a Tagger or a tag filter, switch each tag slot from Local to Asset and pick the tag, since the slot and the object must agree on it.

In the Project window:

  1. Right-click in your Assets folder.
  2. Select Create → Jungle → Filtering → Tag.
  3. Name it Red.
  4. Repeat to create a Blue tag.

Tags are identities, not data

Key assets carry no data beyond their identity (and an optional description). Two tags are "different" if they are different ScriptableObject assets. The asset name is for your reference.


3. Label Your Objects

Tell each cube which color it is. Tags live on the GameObject via a Tagger component — not on the AttachableObject itself.

Select RedCube. Add a Tagger component (menu: Jungle / Filtering / Tagger). In its Tags list, add the Red tag.

Select BlueCube. Add a Tagger and add the Blue tag.


4. Label Your Slots

Do the same for the receiving slots.

Select RedSlot. Add a Tagger component and add the Red tag.

Select BlueSlot. Add a Tagger and add the Blue tag.

Objects and slots can carry multiple tags

A single Tagger can hold many tags. A PurpleCube could carry both Red and Blue, and a UniversalSlot could too.


5. Add a Filter That Enforces the Tags

Tags alone are just labels — they don't block anything yet. You need a filter that checks whether an incoming object's tags match the slot's requirements.

Select RedSlot. In its AttachmentPoint, scroll to the Attachable Filters list inside the Filtering section. Click + and pick Filter (the GameObjectFilterAttachableCheck) — the slot already knows it is filtering attachables, so checks are added directly with no umbrella wrapper.

Inside the new check, the Filter field accepts any IGameObjectFilter. Pick Tag (JungleTagFilter) and configure it:

Field Value
Required Tags Red
Requirement Any

Repeat for BlueSlot with the Blue tag.

Where to put the filter

Filters can live in three places:

  1. On the slot's Attachable Filters — the slot decides which objects it accepts.
  2. On the object's Point Filter — the object decides which slots it tolerates.
  3. On the agent's Grab Filters / Drop Filters — the agent enforces a global rule during a transfer.

Slot-side is the most intuitive — each slot owns its acceptance rule.


6. Test the Filtering

Press Play. Have the agent attempt every combination:

  • RedCube → RedSlot — succeeds. The red tag satisfies the filter.
  • RedCube → BlueSlot — rejected. The red tag does not satisfy the blue filter.
  • BlueCube → BlueSlot — succeeds.
  • BlueCube → RedSlot — rejected.

When a transfer is rejected, the agent silently picks the next eligible candidate (or fails the drop if none are valid). No exceptions thrown.

Why the rejection was silent

The AttachingAgent buffers rejection reasons internally — open the agent's Debug panel in the Editor to see exactly which filter or condition rejected each candidate. See the AttachingAgent reference for the rejection record API.


7. Filter Requirement Modes

The JungleTagFilter exposes a Requirement mode that controls how the required tag list is evaluated.

All — "must have every tag"

Filter requires: [Red, Heavy]
Object has: [Red, Heavy, Fragile]   → PASS
Object has: [Red]                   → FAIL (missing Heavy)

Any — "must have at least one"

Filter requires: [Red, Blue]
Object has: [Red]    → PASS
Object has: [Green]  → FAIL

One — "must match exactly one"

Filter requires: [Red, Blue, Green]
Object has: [Red]        → PASS
Object has: [Red, Blue]  → FAIL (two matches)

AnyExcept — "must have none of these"

Filter requires: [Fragile]
Object has: [Heavy, Red]      → PASS (no Fragile)
Object has: [Fragile, Red]    → FAIL

AnyExcept in practice

A Trash Bin slot with an AnyExcept filter for [Valuable] accepts any object except those tagged as valuable.


8. Combining Multiple Filters

You can add multiple filters to the same list. All filters must pass — the chain is AND-evaluated.

For example, on a single slot's Attachable Filters list:

  1. Filter (with a JungleTagFilter inside) — requires the Red tag.
  2. Held State Filter — requires the object to not be currently attached elsewhere.

The result: a slot that only accepts free, red-tagged objects.

Check lists are always allowlists

A check/filter slot in Octoputs always means allow only what passes. To express "reject these", invert at the leaf — for tags, use the AnyExcept mode. There is no top-level denylist.


9. Object-Side Filters: When the Object Picks Slots

The flip side: an object that's choosy about which slots it accepts. On the AttachableObject's Point Filter list, add a Filter check (GameObjectFilterAttachmentPointCheck) with a JungleTagFilter inside, requiring, say, Heavy Duty Slot. Now this specific object will refuse any slot that doesn't carry that tag — useful for objects that need infrastructure (a battery requires a charging dock, a key requires a keyhole).

The other AttachmentPoint checks available:

Check What it tests
IsHoldingCheck Whether the slot currently holds anything.
CanAttachCheck Whether the slot's own conditions allow attaching a specific object.
PhaseCheck Current lifecycle phase (Idle / Attaching / Attached / Detaching).
OnAttachedObjectCheck Delegates to nested attachable checks evaluated on whatever the point currently holds.
NotJustDetachedCheck Hides a point after a watched attachable detaches from it, with a pluggable reset (distance / time / detector focus).

Next Steps