Objects¶
Reference, find, and manage GameObjects and Components as configurable values - enable, disable, instantiate, and pool objects.
Jungle.Objects gives you Inspector-configurable operations for scene objects and UI elements. You can activate or deactivate GameObjects, reparent them, set positions, change layers, control CanvasGroup properties, transfer objects between storages, and manage object pools - all without writing custom scripts. The package builds on the value provider and process systems, so every object reference is swappable from the Inspector.
Assembly: Jungle.Objects (depends on Jungle.Core)
Namespace: Jungle.Objects
GameObject Value Providers¶
Value providers give you a flexible way to reference GameObjects. Instead of hard-wiring a reference, you pick a source strategy from the Inspector - a direct reference, a shared ScriptableObject asset, the first object in a storage, the last detected object, and so on. The consuming code stays the same regardless of where the reference comes from.
All value providers implement IGameObjectValue (which extends IValue<GameObject>). Use them anywhere a process, command, or modifier needs a GameObject reference.
| Provider | Category | Description |
|---|---|---|
| GameObject Value | (default) | Direct serialized reference to a GameObject. |
| GameObject List | (default) | Several objects in order, each entry picked its own way: a direct reference, the context, a container, a detector, a search. Drag several objects onto the list to add one entry per object. Reactors update when any entry changes. |
| GameObject Value From Asset | Lookup | Reads from a shared GameObjectValueAsset ScriptableObject. |
| From Selection | Selection | Runs an object-selection chain from a root and yields the matching set — hierarchy walk, tag/allowlist filter (a filter is a one-step selection), related-object lookup, Sequence/Union, … e.g. "every child of X tagged Pickup" or simply "this set, filtered". Caches on first use by default; re-evaluates live when the root is observable or you opt in. |
| All In Scene | Scene | Every GameObject in the loaded scene(s) via a scene scan. Heavy, so meant for setup: it resolves once on first use by default, and searching again on a later frame logs a warning. Enable re-evaluation only to track runtime spawns/destroys, or include inactive objects. To reach a known group of objects while playing, use a GameObject Container asset instead. |
| Scene Objects With Tag | Scene | Every active object whose Tagger matches the tags. Searches the whole scene on each read, so use it at setup only (fill a container or value on start); searching again on a later frame logs a warning. |
| GameObject At Index | Lookup | Picks one GameObject from a multi-value source by a wrapping index — pair with a counter to cycle through a set. |
| From Storage | Storage | Picks a GameObject from a container component or asset (first, last, or random). |
| First In Storage | Storage | Returns the first available object in a storage. |
| Last In Storage | Storage | Returns the last available object in a storage. |
| All In Storage | Storage | Returns all objects in a storage as a multi-value provider. |
| All Detected | Detector | All GameObjects currently seen by a Detector. |
| Last Detected | Detector | The most recently detected GameObject. |
| Last Removed From Detector | Detector | The most recently lost/removed GameObject. |
| Children Of | Selection | The objects below a start object: a bone chain (first child down), the start's direct children, or its whole subtree, optionally capped at a count. Resolves once and caches by default; re-evaluates live when the start is observable or you opt in. |
| Filtered Object | Context | The object the surrounding filter is currently evaluating. Only available inside GameObjectFilter graphs — see contextual values. |
GameObject Container asset¶
A container comes two ways: a GameObject List Container component on an object in the scene, or a GameObject Container asset in the Project window. Both hold objects the same way, with the same capacity and take/store options, and every container field accepts either. Use the asset when objects in different scenes or prefabs need to reach the same group while playing: every stand on a table, every enemy on the field, every stash near the player.
- Create the asset: Create > Jungle > Objects > GameObject Container.
- On each object that belongs to it, add a Process Component set to Enable / Disable with a Value Command holding Add To Container While Active, pointed at the asset. Put it on the prefab and every copy joins.
- Where you need the objects, pick All In Container (or Closest, with All In Container as its candidates) and point its Container at the asset.
An object leaves when it is disabled or destroyed, so the asset always holds the objects that are there right now. Each time you press Play it goes back to its starting objects (Items), because an asset cannot keep scene objects between sessions.
Usage¶
Declare a value provider field on any serialized class:
[SerializeReference] [JungleClassSelection]
private IGameObjectValue target = new GameObjectValue();
Then resolve it at runtime:
The user picks the concrete source in the Inspector through the class selection system. The code never changes.
Container Value Providers¶
Container references also use the value system. IGameObjectContainerValue extends IValue<IItemContainer<GameObject>>.
| Provider | Description |
|---|---|
GameObjectContainerValue |
A GameObject List Container component, or a shared GameObject Container asset. |
You can also use SmartGameObjectContainer, which finds a GameObject List Container component on an object, its parents or its children.
CanvasGroup Value¶
For UI workflows, SmartCanvasGroup provides a CanvasGroup reference the same way SmartGameObject provides GameObjects:
Commands¶
GameObjectCommand¶
A modular command that runs a configurable list of IGameObjectOperation operations on a single target. Instead of creating separate components for each operation, compose them in one command. Extends TargetedCommand<GameObject, IGameObjectOperation>.
[Serializable]
public class GameObjectCommand : TargetedCommand<GameObject, IGameObjectOperation>
{
[TargetField]
[SerializeField]
private SmartGameObject target;
[SerializeReference]
[JungleList(typeof(IGameObjectOperation), Layout = JungleListLayout.Flat, EmptyLabel = "No operations", ElementLabel = "Operation")]
private List<IGameObjectOperation> operations = new();
protected override IList<IGameObjectOperation> GetOperations() => operations;
protected override void BeginOperation(IGameObjectOperation op, GameObject go, Action onComplete)
=> op.Begin(go, onComplete);
}
- Target: the object the operations act on.
- Operations: add, remove and drag to reorder.
Available Operations¶
| Operation | Description |
|---|---|
| Activate | Enable or disable the GameObject's active state. |
| Toggle Active | Flips the GameObject's active state: on becomes off, off becomes on. Use for open/close panels and show/hide toggles driven by a single input. |
| Reactivate | Turns the GameObject off then on again in one step, so anything that runs on enable starts over. Use to replay a one-shot particle system or restart an animation. |
| Set Parent | Reparent under a new transform (world position preserved by default). |
| Set Position | Set world or local position. Uses SmartVector3 for dynamic sources. |
| Set Rotation | Rotate by Euler angles measured against a frame: the object's own axes (default, turns it by that much), the world, its parent, or a custom position and facing it turns around. |
| Set Scale | Set local scale. |
| Set Layer | Change the physics/rendering layer. Optionally recursive to children. |
| Set Tag | Change the GameObject's tag at runtime. |
Each operation implements IGameObjectOperation:
public interface IGameObjectOperation : IOperation
{
void Begin(GameObject gameObject, Action onComplete);
}
UICommand¶
The UI equivalent of GameObjectCommand. Runs a list of IUIOperation operations on a single CanvasGroup. Extends TargetedCommand<CanvasGroup, IUIOperation>.
[Serializable]
public class UICommand : TargetedCommand<CanvasGroup, IUIOperation>
{
[TargetField]
[SerializeReference] [JungleClassSelection]
private ICanvasGroupValue target = new CanvasGroupValue();
[SerializeReference]
[JungleClassSelection(typeof(IUIOperation), Inline = true, EmptyLabel = "No operations", ElementLabel = "Operation")]
private List<IUIOperation> operations = new();
protected override CanvasGroup ResolveTarget() => target?.V;
protected override IList<IUIOperation> GetOperations() => operations;
protected override void BeginOperation(IUIOperation op, CanvasGroup cg, Action onComplete)
=> op.Begin(cg, onComplete);
}
Available UI Operations¶
| Operation | Description |
|---|---|
| Set Alpha | Sets canvasGroup.alpha through a float pipeline (supports modifiers like clamp, remap, ease). |
| Set Blocks Raycasts | Enable, disable, or toggle blocksRaycasts. |
| Set Interactable | Enable, disable, or toggle interactable. |
Storage¶
IItemContainer<GameObject>¶
The contract every GameObject container implements: the GameObject List Container component, the GameObject Container asset, and the creator-backed container. Any process or command that takes a container field works with any of them.
Key API:
public interface IItemContainer<GameObject>
{
IReadOnlyList<GameObject> Available { get; }
int Count { get; }
int Capacity { get; }
GameObject LastAdded { get; }
GameObject LastRemoved { get; }
GameObject TryTake();
bool TryReturn(GameObject item);
bool TryRemove(GameObject item);
bool CanAccept(GameObject item);
void Take(Action<GameObject> onReady);
void Store(GameObject item, Action<bool> onComplete);
}
GameObjectListContainer and GameObject Container asset¶
A list-backed container, as a scene component or as a project asset (see GameObject Container asset). Both share the same logic (GameObjectList).
- Component menu:
Jungle > Data > GameObject List Container; asset menu:Create > Jungle > Objects > GameObject Container - Configurable
capacity(-1 for unlimited) and optional take/store processes - LIFO ordering:
TryTake()removes the last item - Items are the starting objects, each picked its own way (a direct reference, a search, another container); the container reads them on first use
- Items: the starting objects. Drag objects onto the list to add them.
- Capacity: -1 means unlimited.
- Take and Store Process: optional steps that run as objects leave or arrive.
Container Transfer¶
Moving objects between containers is a ContainerCommand hosting a TransferOperation. The operation takes from the source and stores in the destination, and returns the item to the source if the destination rejects it. Because it is an IOperation, it completes only after the full take-then-store chain finishes.
// The operation's two container fields:
[SerializeReference] [JungleClassSelection]
private IGameObjectContainerValue source;
[SerializeReference] [JungleClassSelection]
private IGameObjectContainerValue destination;
Object Pooling¶
Pooling is a creator, not a container: PooledObjectCreator is the component you add, and the reserve it manages internally is a GameObjectPool. Anything that takes a SmartCreator (or a GameObjectCreator reference) can therefore be pooled by swapping the creator, with no other change. Wrap it in a GameObjectCreatorBackedContainer when something needs take/store container semantics on top.
PooledObjectCreator¶
- Component menu:
Jungle > Creator > Pooled Object Creator - Pre-instantiates a configurable number of objects on
Awake - Grows on demand up to an optional
maxCount - Enforces a
maxActivelimit (oldest acquired object is force-returned when exceeded)
PooledObjectCreator
Prefab: Bullet (a PoolObject is added at runtime if missing)
Initial Count: 10
Max Count: 50 (0 = unlimited)
Pool Parent: (this transform)
Max Active: 0 (0 = unlimited)
To pool several prefabs behind one component, use KeyedPooledObjectCreator.
PoolObject¶
Attach to the pooled prefab. Manages the acquire/release lifecycle:
- Acquire: activates the GameObject, arms the return trigger, fires
OnAcquired - Release: disarms the trigger, runs the back-to-pool process, deactivates, fires
OnReleased
Optional configurable fields:
| Field | Description |
|---|---|
| Return Trigger | IPoolReturnTrigger - determines when the object auto-returns. |
| Out Of Pool Process | IProcess to run when the object is acquired (e.g., a spawn animation). |
| Back To Pool Process | IProcess to run when the object is released (e.g., a fade-out). |
Return Triggers¶
| Trigger | Description |
|---|---|
| On Disable | Returns to pool when the GameObject is disabled externally. |
| Timer | Returns to pool after a configurable delay (seconds). |
Implement IPoolReturnTrigger for custom return logic:
public interface IPoolReturnTrigger
{
void Arm(PoolObject poolObject); // Start monitoring
void Disarm(); // Stop monitoring
}
Pool Workflow¶
flowchart LR
subgraph PooledObjectCreator
I[Inactive List]
end
subgraph Scene
A[Active Objects]
end
I -->|TryTake / Acquire| A
A -->|Release / Return Trigger| I
PoolStorage.TryTake()removes an object from the inactive list and adds it to activePoolObject.Acquire()activates the GameObject and arms the return trigger- When the trigger fires (or
Release()is called), the object deactivates and returns to the inactive list - The optional out-of-pool and back-to-pool processes run during acquire/release transitions
Spawn and per-spawn commands¶
Spawn and Spawn Over Time run their per-spawn commands once for each new object, each in its own run. Inside them, Each Object is the object just spawned and Context is still the object of the outer run, so a command can act on the spawn and read the detected item at the same time. Spawns are handled one after another. Commands added to the list get their target set to Each Object.
Utility Extensions¶
The package includes convenience extension methods in the Jungle namespace:
MonoBehaviourExt¶
// Delayed execution (uses UpdateManager, no coroutine needed)
this.StartDelayed(0.5f, () => DoSomething());
ObjectExt¶
// Repeat an action N times
5.Times(() => SpawnEnemy());
5.Times(i => SpawnEnemy(i));
// Activation shortcuts
gameObject.SetActive(); // SetActive(true)
gameObject.SetInactive(); // SetActive(false)
// Create child/sibling GameObjects
var child = gameObject.CreateNewChildGameObject("Child");
var sibling = gameObject.CreateNewSiblingGameObject("Sibling");