Physics¶
Read physics data, apply forces, and react to collisions - all configurable in the Inspector.
Jungle.Physics lets you work with Unity's physics engine without writing custom scripts. Apply forces and torques, set velocities, toggle kinematic mode, control colliders, navigate with NavMeshAgents, cast rays, and respond to collision and trigger events - all through composable commands you configure in the Inspector. For continuous behaviors like force pipelines or velocity decay, timed operations self-tick on FixedUpdate and handle timing automatically.
The package covers:
- Value providers for Rigidbody, Collider, RaycastHit, gravity, and collision matrix data
- Commands for composable physics, collider, NavMesh, physics settings, and raycast operations
- Operations for both instant and timed physics behaviors (velocity decay, force pipelines)
- Events that fire on collision and trigger callbacks
- Raycasting utilities with caching and optional Jobs-based batching
- Detection strategies for raycast and trigger-based object detection
Assembly dependencies: Jungle.Core, Jungle.Spatial, Jungle.Math, IProcess, Unity.Mathematics, Unity.Collections, Unity.Burst (optional, enables batched raycasting via JUNGLE_JOBS_ENABLED).
Value Providers¶
Value providers let you wire physics data - a Rigidbody reference, a raycast hit point, the global gravity vector - into any system that accepts a value source. Pick the provider you need from the Inspector dropdown; the consuming system never changes.
Technically, physics value providers follow the standard IValue<T> pattern. Use them with [SerializeReference] and [JungleClassSelection] to wire physics data into any system that accepts a value provider.
Rigidbody and Collider¶
| Type | Interface | Description |
|---|---|---|
SmartRigidbody |
ISmartComponent<Rigidbody> |
A Rigidbody field: direct reference, lookup, or resolved at runtime |
SmartRigidbody2D |
ISmartComponent<Rigidbody2D> |
The 2D equivalent |
SmartCollider |
ISmartComponent<Collider> |
A Collider field, same three modes |
// Wire a Rigidbody into any system that needs one
[SerializeField]
private SmartRigidbody targetRigidbody;
// Read the Rigidbody
Rigidbody rb = targetRigidbody.Value;
See Smart Values for the Local / Dynamic / Copied-On-Init modes these fields share.
RaycastHit Data¶
| Type | Interface | Description |
|---|---|---|
CollisionHitValue |
ICollisionHitValue |
Stores a RaycastHit struct (point, normal, collider, etc.) |
CollisionHitPositionValue |
IVector3Value |
Reads the hit position from an ICollisionHitValue |
CollisionHitNormalValue |
IVector3Value |
Reads the hit normal from an ICollisionHitValue |
These compose together: a RaycastHitCaptureCommand writes into a CollisionHitValue, and downstream systems read the position or normal through the derived values.
// Read hit position from a stored collision hit
[SerializeReference] [JungleClassSelection]
private IVector3Value hitPosition = new CollisionHitPositionValue();
Vector3 pos = hitPosition.Value();
Other Values¶
| Type | Interface | Description |
|---|---|---|
GravityValue |
IVector3Value |
Returns Physics.gravity - the global gravity vector |
SmartNavMeshAgent |
ISmartComponent<NavMeshAgent> |
A NavMeshAgent field |
Bounds-Driven Sizes¶
Several spatial value converters in jungle.spatial turn a Bounds into the size inputs physics queries expect. Combine with LocalGameObjectBounds and a Filtered Object source to drive shapes from the object being checked, not a hardcoded number.
| Type | Output | Use For |
|---|---|---|
BoundsSphereRadius |
IFloatValue |
Sphere overlap / sphere-cast radius. |
BoundsExtents |
IVector3Value |
Box overlap half-extents (or full size). Per-axis multiplier. |
BoundsHeight |
IFloatValue |
Single-axis size — capsule height, vertical-extent checks. Per-axis selection (X/Y/Z). |
Filters¶
PhysicsOverlapFilter¶
A GameObjectFilter that probes for colliders around the filtered object's transform with a configurable shape (sphere / box / capsule). Use it as a detector predicate to express conditions like "only objects currently touching the floor" or "only objects clear of obstacles".
| Field | Description |
|---|---|
shape |
Probe shape: Sphere, Box, or Capsule. |
collisionMask (SmartLayerMask) |
Layers that count for the overlap. |
triggerInteraction |
Whether triggers count, are ignored, or follow project default. |
ignoreSelfColliders |
Skip colliders on the filtered object or its children. |
rigidbodyRequirement |
Filter results by attached rigidbody: Any, AnyRigidbody, NonKinematicOnly, KinematicOnly. |
hitFilters |
IGameObjectFilter list run on each touching collider's GameObject; it counts only when all pass. Empty counts every collider. |
passOnOverlap |
true = filter passes when at least one collider overlaps. false = passes when clear. |
sphereRadius (Sphere) |
SmartFloat. Drive from bounds via BoundsSphereRadius. |
boxHalfExtents (Box) |
SmartVector3. Drive from bounds via BoundsExtents (HalfExtents mode). |
capsuleRadius, capsuleHeight, capsuleAxis (Capsule) |
SmartFloat/SmartFloat/enum. Height is auto-clamped to ≥ 2 × radius. |
Sized-by-bounds wiring. Inside the filter, the IGameObjectValue slot in LocalGameObjectBounds will offer Filtered Object in the picker (and only there — the picker hides it elsewhere). Wiring it makes the probe size scale automatically per filtered object:
PhysicsOverlapFilter
└─ sphereRadius = SmartFloat (Dynamic)
└─ Bounds Sphere Radius
└─ Local GameObject Bounds
└─ gameObject = Filtered Object
The filter uses Physics.OverlapXxxNonAlloc with a fixed-size buffer (16) so it's allocation-free per call.
Commands¶
Commands are composable, one-shot operations. All physics commands follow the TargetedCommand<TTarget, TOperation> pattern: one target, multiple operations in a reorderable list. Operations run in parallel - instant ones complete immediately, timed ones self-tick. The command completes when all operations finish.
RigidBodyCommand¶
Extends TargetedCommand<Rigidbody, IPhysicsOperation>. Resolves a single Rigidbody and executes a list of IPhysicsOperation operations on it.
- Target: the Rigidbody every operation acts on.
- Operations: one-line ones like Set Kinematic stay on a single row.
[SerializeReference]
[JungleList(typeof(IPhysicsOperation), Layout = JungleListLayout.Flat, EmptyLabel = "No operations", ElementLabel = "Operation")]
private List<IPhysicsOperation> operations = new();
// The Rigidbody target comes from the base command's SmartRigidbody field.
Built-in physics operations:
| Operation | Description |
|---|---|
ApplyForce |
Applies a force vector with configurable ForceMode. Optionally applies at a custom world position for torque effects. |
ApplyTorque |
Applies a torque vector with configurable ForceMode. |
SetLinearVelocityAction |
Directly sets the rigidbody's linear velocity. |
SetAngularVelocityAction |
Directly sets the rigidbody's angular velocity. |
SetKinematic |
Sets kinematic, non-kinematic, or toggles. |
SetGravity |
Enables, disables, or toggles useGravity. |
SetLinearDamping |
Sets the rigidbody's linear damping (air resistance). |
SetAngularDamping |
Sets the rigidbody's angular damping (rotational resistance). |
SetConstraints |
Sets RigidbodyConstraints to freeze specific axes. |
SetMass |
Sets the Rigidbody mass. |
ForcePipelineOperation |
Reads a Vector3 target and applies it as a force each fixed tick. Optionally applies at a custom world position. Timed operation. |
TorquePipelineOperation |
Reads a Vector3 target and applies it as torque each fixed tick. Timed operation. |
QuaternionTorquePipelineOperation |
Converts a quaternion rotation target into proportional torque impulses with configurable strength and damping. Timed operation. |
LinearVelocityPipeline |
Drives the rigidbody's linear velocity each fixed tick via a Vector3 target + modifier chain with a configurable completion check. Timed operation. |
AngularVelocityPipeline |
Drives the rigidbody's angular velocity each fixed tick via a Vector3 target + modifier chain with a configurable completion check. Timed operation. |
SetDetectCollisions |
Turns collision detection for the whole rigidbody on or off, covering every collider it owns. Turn it off while an object is carried so it cannot bump or push anything, and back on when it is released. While off, raycasts cannot see the object either. |
SetExcludeLayers |
Chooses the layers the rigidbody passes through, covering every collider it owns. Raycasts still hit it, so an object parked in a slot with Everything excluded cannot bump anything yet stays hoverable and grabbable. Set it back to Nothing on release. |
Example - launch an object upward and disable gravity:
var command = new RigidBodyCommand(
new ApplyForce { force = Vector3.up * 10f, forceMode = ForceMode.Impulse },
new SetGravity { mode = SetGravity.GravityMode.Disable }
);
command.Begin();
ColliderCommand¶
Extends TargetedCommand<Collider, IColliderOperation>. Resolves a single Collider and executes a list of IColliderOperation operations on it.
Built-in collider operations:
| Operation | Description |
|---|---|
SetEnabled |
Enables, disables, or toggles the collider. |
SetTrigger |
Controls the isTrigger flag. |
SetPhysicsMaterial |
Assigns a PhysicsMaterial to the collider. |
IgnoreCollisionWith |
Makes this collider and one other collider pass through each other, or collide again. Only that exact pair is affected -- no layer or collision matrix setup needed. Unity forgets the pairing whenever either collider is disabled. |
NavMeshAgentCommand¶
Extends TargetedCommand<NavMeshAgent, INavMeshOperation>. Resolves a single NavMeshAgent and executes a list of INavMeshOperation operations on it.
Built-in NavMesh operations:
| Operation | Description |
|---|---|
SetDestination |
Sets the agent's navigation target (transform or position). |
SetNavMeshSpeed |
Changes agent speed. |
SetNavMeshEnabled |
Enables or disables the agent. |
StopNavMeshAgent |
Stops the agent. |
ResumeNavMeshAgent |
Resumes the agent. |
WarpNavMeshAgent |
Teleports the agent to a position. |
PhysicsSettingsCommand¶
Executes a list of IPhysicsSettingsOperation operations on global physics settings. Unlike the targeted commands above, this one has no target component - it modifies Unity's global Physics settings directly.
Built-in physics settings operations:
| Operation | Description |
|---|---|
SetGravityVector |
Sets the global gravity vector. |
SetPhysicsIterations |
Configures solver iteration counts. |
With Magpile installed, an Apply Collision Matrix operation joins this list. See State & Save.
RaycastHitCaptureCommand¶
Extends Command and executes a list of IRaycastOperation operations in parallel. Each operation performs a physics query (raycast, sphere cast, etc.) and stores results into value references for downstream systems to read.
// Configure in Inspector:
// - Each IRaycastOperation has its own ray origin, direction, and result storage
// - Operations run in parallel
// - Results are written into ICollisionHitValue / IColliderValue references
// On Execute(), the command runs all operations and writes results
// into the storage values for other systems to read.
Operations¶
Operations are the building blocks of physics commands. Each operation implements one of the operation interfaces and is either instant or timed.
Instant vs Timed Operations¶
Instant operations extend a convenience base class (e.g., InstantPhysicsOperation) and override a single Execute() method. They complete immediately when called.
Timed operations implement the operation interface directly (e.g., IPhysicsOperation) along with IFixedUpdatable to self-tick on FixedUpdate. They call onComplete when finished. Force pipelines and velocity decay are examples of timed operations.
Both types can be mixed freely in the same command's operation list - the command runs them in parallel and completes when all finish.
IPhysicsOperation¶
Instant operations extend InstantPhysicsOperation and override Execute(Rigidbody rb). Timed operations implement IPhysicsOperation directly and call onComplete when their work is done.
Pipeline Operations¶
Pipeline operations are timed IPhysicsOperation implementations that run continuously on FixedUpdate. They combine a target value, modifiers, and an applier into a continuous physics-driven loop.
| Operation | Description |
|---|---|
ForcePipelineOperation |
Reads a Vector3 target and applies it as a force to a Rigidbody each fixed tick. Optionally applies at a custom world position. |
TorquePipelineOperation |
Reads a Vector3 target and applies it as torque to a Rigidbody each fixed tick. |
QuaternionTorquePipelineOperation |
Converts a quaternion rotation target into proportional torque impulses with configurable strength and damping. Useful for physics-driven aiming or motorized joints. |
LinearVelocityPipeline |
Drives a Rigidbody's linear velocity each fixed tick via a Vector3 target + modifier chain. |
AngularVelocityPipeline |
Drives a Rigidbody's angular velocity each fixed tick via a Vector3 target + modifier chain. |
Example - throwing an object with velocity decay:
Wire a velocity measurement into a LinearVelocityPipeline's target as the starting value and use a lerped target with a decay curve. The pipeline reads the current linear velocity each FixedUpdate, runs it through the modifier chain, and writes the result back to the rigidbody.
- Destination: the velocity to drive toward, for example the measured throw velocity easing to zero.
- Modifiers: optional changes applied on the way, in order.
Events¶
Physics Event Relays¶
Family of MonoBehaviours that broadcast Unity's physics callbacks as C# events. Add the subclass that matches the callback family you need — each only registers its own Unity messages with the physics engine.
| Component | Listens for |
|---|---|
Trigger3DRelay |
OnTriggerEnter / OnTriggerExit |
Collision3DRelay |
OnCollisionEnter / OnCollisionExit |
Trigger2DRelay |
OnTriggerEnter2D / OnTriggerExit2D |
Collision2DRelay |
OnCollisionEnter2D / OnCollisionExit2D |
Need more than one family on the same GameObject? Add multiple relays — each only subscribes to its own Unity messages. All subclasses share PhysicsEventRelayBase and expose the same events; consumers (PhysicsEvent, PhysicsOverlapDetectionStrategy) only know about the base. Full reference: PhysicsEventRelay.
PhysicsEvent¶
A serializable IEvent implementation that monitors a physics relay. Configure the relay reference, event type, layer mask filter, and tag filter in the Inspector. Errors loudly at bind time if the chosen event type isn't emitted by the wired relay subclass.
// Use a PhysicsEvent to trigger any Jungle system on collision
[SerializeReference] [JungleClassSelection]
private IEvent onHit = new PhysicsEvent();
// In your setup code:
onHit.Register(() => Debug.Log("Something collided!"));
Supported event types (PhysicsEventType):
OnCollisionEnter,OnCollisionExitOnTriggerEnter,OnTriggerExitOnCollisionEnter2D,OnCollisionExit2DOnTriggerEnter2D,OnTriggerExit2D
Filtering: Set the layerFilter mask and/or tagFilter list to restrict which colliding objects cause the event to fire.
Joints¶
JointBreakSignalSource¶
A MonoBehaviour that forwards Unity's OnJointBreak callback as a signal into a Reactor. Add it to the same GameObject that owns the joint.
| Field | Description |
|---|---|
reactor |
Reactor that receives the signal. If empty, searched on this GameObject (and optionally parents/children). |
searchParents |
Search parent hierarchy for a Reactor when none is assigned. |
searchChildren |
Search child hierarchy for a Reactor when none is assigned. |
signal |
Signal Key pushed into the Reactor when the joint breaks. Leave empty to skip the dispatch and only fire the local event. |
onBroken |
UnityEvent\<float> invoked locally with the break force. |
Wire a Signal Reaction on the target Reactor to run processes when the joint snaps. The onBroken event also fires with the break force value for local wiring.
Joint Measurement Command¶
Measures a joint for as long as it runs. Pick Joint Measurement Command as the process of a Process Component (or in a reaction's process), set its target to the joint, and add measurements. Each measurement writes into its own sink, for example a Float From Data Storage key, so a Reactor can watch thresholds on it. Measurements that need a specific joint type skip other joints.
| Field | Description |
|---|---|
| Target | The joint to measure. |
| Measurements | The joint measurements to run. Each writes into its own sink. |
- Target: the joint to measure.
- Scheduler: how often it samples.
- Sink: where the angle is written.
Joint Measurements¶
| Measurement | Output | Description |
|---|---|---|
| Hinge Angle | float | Current angle of a HingeJoint relative to its rest pose. |
| Hinge Angular Velocity | float | Angular velocity of a HingeJoint. |
| Joint Distance | float | World-space distance between the joint's anchor and its connected anchor. Detects stretch on spring or configurable joints. |
| Joint Force | float | Magnitude of the force the joint currently applies. |
| Joint Torque | float | Magnitude of the torque the joint currently applies. |
| Configurable Joint Twist | float | Twist angle of a ConfigurableJoint around its primary axis. |
| Configurable Joint Swing 1 | float | Swing angle of a ConfigurableJoint around its secondary axis. |
| Configurable Joint Swing 2 | float | Swing angle of a ConfigurableJoint around its tertiary axis. |
Each measurement supports an optional modifier chain (clamping, remapping, curves; smoothing and filters come with Anteloope) and a configurable execution frequency. Pair with a Float Threshold or Float Range reaction on the same value to fire processes when values cross a boundary.
Raycasting¶
RaycastHitProvider¶
A serializable raycasting utility that encapsulates ray source, layer mask, max distance, trigger handling, caching, and optional batch processing.
- Ray Value: where the ray starts and points.
- Caching: cast less often; the interval field follows the mode.
- Batch: share the work across all raycasters when jobs are enabled.
Key features:
- Ray source - configurable via
IRayValue(defaults to camera ray from mouse position) - Caching - time-based or frame-based intervals to reduce raycast frequency
- Batch raycasting - when
JUNGLE_JOBS_ENABLEDis defined, raycasts are submitted to theRaycastPerformanceManagerfor parallel execution via Unity Jobs; each result arrives one frame after its request
// Use a hit provider in your own systems
var raycaster = new RaycastHitProvider();
if (raycaster.TryGetHit(out RaycastHit hit))
{
Debug.Log($"Hit {hit.collider.name} at {hit.point}");
}
Sharing raycasters: Put the configuration on a HitProviderAsset and drop a HitProviderFromAsset into any IHitProvider field, so several components cast the same way without each carrying its own copy.
SpreadNormalSampler¶
A static utility that averages surface normals from multiple rays spread in a cone pattern around a central ray. Useful for smoothing normals near surface edges.
Vector3 smoothedNormal = SpreadNormalSampler.Sample(
mainNormal: hit.normal,
mainRay: ray,
sampleCount: 8,
spreadAngleDeg: 5f,
maxDistance: 100f,
layerMask: ~0
);
RaycastPerformanceManager¶
A singleton that batches all raycast requests into a single RaycastCommand.ScheduleBatch call per frame using Unity Jobs. Only available when JUNGLE_JOBS_ENABLED is defined (requires the Burst package). Hit providers opt into this automatically via their useBatchRaycast toggle.
Detection Strategies¶
Detection strategies integrate with Jungle's detector system to report when objects enter or leave detection range.
| Strategy | Description |
|---|---|
RaycastDetectionStrategy |
Periodically casts a ray and reports the hit GameObject. Only one object is detected at a time - when the ray hits a new object, the previous one is reported as lost. |
PhysicsOverlapDetectionStrategy (shown as Trigger & Collision) |
Listens to a physics relay for enter/exit pairs. Pick the relay subclass to choose which Unity callbacks the engine actually fires (Trigger3DRelay, Collision3DRelay, or the 2D variants). Supports layer mask filtering. |
// Configure a trigger-based detector in the Inspector
[SerializeReference] [JungleClassSelection]
private IDetectionStrategy detection = new PhysicsOverlapDetectionStrategy();
Utilities¶
RigidbodyExt¶
Extension methods on Rigidbody for common physics operations:
| Method | Description |
|---|---|
Teleport(position, motionKept, jointAttached) |
Teleports a rigidbody (and optionally joint-attached bodies) while preserving or resetting velocity. Handles the kinematic toggle required for reliable position changes. |
GetPushForceNeeded(target, ...) |
Calculates the force needed to push a rigidbody toward a target position, with configurable velocity and force clamping. |
TargetPosition(target, ...) |
Applies the calculated push force directly. |
TargetLookAt(lookDirection, normal, ...) |
Applies torque to rotate a rigidbody toward a look direction with angular velocity clamping. |