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 Array Value | (default) | Serialized array of GameObjects. Supports multi-value access. |
| GameObject Value From Asset | Lookup | Reads from a shared GameObjectValueAsset ScriptableObject. |
| GameObject List From Asset | Lookup | Reads from a shared GameObjectListValueAsset ScriptableObject. |
| Value From Reference | Lookup | Reads from a GameObjectValueReference component in the scene. |
| Filtered Set | Lookup | Wraps another multi-value source and keeps only the GameObjects that pass an allowlist filter. Empty filter = keep all. Forwards change notifications when the wrapped source is observable. |
| From Storage | Storage | Picks a GameObject from a GameObjectStorage (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 DetectorBase. |
| Last Detected | Detector | The most recently detected GameObject. |
| Last Removed From Detector | Detector | The most recently lost/removed GameObject. |
| Filtered Object | Context | The object the surrounding filter is currently evaluating. Only available inside GameObjectFilter graphs — see contextual values. |
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.
GameObjectValueReference¶
A MonoBehaviour that holds a settable ISettableGameObjectValue and fires processes when the value changes. Use it as a reactive binding point in the scene:
// Other code can write to it
reference.SetValue(someGameObject);
// Configured on-change processes automatically fire when the value changes
// Clear it
reference.Clear();
Storage Value Providers¶
Storage references also use the value system. IGameObjectStorageValue extends IValue<GameObjectStorage>.
| Provider | Description |
|---|---|
| Storage Value | Direct reference to a GameObjectStorage component. |
| Storage Value Asset | Reads from a shared GameObjectStorageValueAsset ScriptableObject. |
| Storage From Asset | Alias for reading a storage reference from a ScriptableObject asset. |
CanvasGroup Value¶
For UI workflows, ICanvasGroupValue provides a CanvasGroup reference the same way IGameObjectValue provides GameObjects:
[SerializeReference] [JungleClassSelection]
private ICanvasGroupValue target = new CanvasGroupValue();
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]
[SerializeReference] [JungleClassSelection]
private IGameObjectValue target = new GameObjectValue();
[SerializeReference]
[JungleClassSelection(typeof(IGameObjectOperation), Inline = true, EmptyLabel = "No operations", ElementLabel = "Operation")]
private List<IGameObjectOperation> operations = new();
protected override GameObject ResolveTarget() =>
OverrideTarget ? OverrideTarget : target?.V;
protected override IList<IGameObjectOperation> GetOperations() => operations;
protected override void BeginOperation(IGameObjectOperation op, GameObject go, Action onComplete)
=> op.Begin(go, onComplete);
}
Available Operations¶
| Operation | Description |
|---|---|
| Activate | Enable, disable, or toggle the GameObject's active state. |
| 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 | Set world or local rotation via Euler angles. |
| 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() =>
OverrideTarget ? OverrideTarget.GetComponent<CanvasGroup>() : 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¶
GameObjectStorage¶
The abstract base class for all storages that hold GameObjects. Concrete implementations are assigned in the Inspector. Any process or command that takes a GameObjectStorage field works with any implementation.
Key API:
public abstract class GameObjectStorage : ItemStorage<GameObject>
{
IEnumerable<GameObject> Available { get; }
int Count { get; }
int Capacity { 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);
}
GameObjectListStorage¶
A simple list-backed storage. Items can be pre-assigned in the Inspector or added/removed at runtime.
- Component menu:
Jungle > Storage > GameObject List Storage - Configurable
capacity(-1 for unlimited) - LIFO ordering:
TryTake()removes the last item
Storage Transfer¶
Two ways to move objects between storages:
| Type | Description |
|---|---|
| StorageTransferCommand | Fire-and-forget. Takes from source, stores in destination, completes immediately. If the destination rejects the item, it is returned to the source. |
| StorageTransferProcess | Same logic but implements IProcess - completes only after the full take-then-store chain finishes. |
// Both use the same field pattern:
[SerializeReference] [JungleClassSelection]
private IGameObjectStorageValue source;
[SerializeReference] [JungleClassSelection]
private IGameObjectStorageValue destination;
Object Pooling¶
The pooling system is built on top of GameObjectStorage, so pools integrate seamlessly with storage-based commands and value providers.
PoolStorage¶
A GameObjectStorage that manages a pool of prefab instances.
- Component menu:
Jungle > Storage > Pool Storage - 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)
PoolStorage
Prefab: Bullet (must have PoolObject component)
Initial Count: 10
Max Count: 50 (0 = unlimited)
Pool Parent: (this transform)
Max Active: 0 (0 = unlimited)
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 PoolStorage
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
SharedTargetCommands¶
Resolves a target from an IGameObjectValue, injects it into all inner ITargetedCommand children, then runs them. Use for orchestrating multiple commands on a dynamically resolved object.
// Configured in Inspector:
// Target: IGameObjectValue (resolved at runtime)
// Commands: List<ITargetedCommand>
The target GameObject is set as OverrideTarget on each command before execution. When nested inside another targeted context, the target field is hidden and inherited from the parent. Completion fires after all inner commands finish.
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");