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 |
|---|---|---|
RigidbodyValue |
IRigidbodyValue / ISettableRigidbodyValue |
Direct reference to a Rigidbody component |
ColliderValue |
IColliderValue / ISettableColliderValue |
Direct reference to a Collider component |
// Wire a Rigidbody into any system that needs one
[SerializeReference] [JungleClassSelection]
private IRigidbodyValue targetRigidbody = new RigidbodyValue();
// Read the Rigidbody
Rigidbody rb = targetRigidbody.V;
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 |
CollisionMatrixValue |
ICollisionMatrixValue |
Stores a CollisionLayerMatrix snapshot |
NavMeshAgentValue |
INavMeshAgentValue |
Direct reference to a NavMeshAgent component |
PhysicsEventRelayValue |
IPhysicsEventRelayValue |
Direct reference to a PhysicsEventRelay component |
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. |
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 toggleable 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.
[SerializeReference] [JungleClassSelection]
private IRigidbodyValue targetRigidbody = new RigidbodyValue();
[SerializeReference]
[JungleClassSelection(typeof(IPhysicsOperation), Inline = true, EmptyLabel = "No operations", ElementLabel = "Operation")]
private List<IPhysicsOperation> operations = new();
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. |
SetLinearVelocity |
Directly sets the rigidbody's linear velocity. |
SetAngularVelocity |
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. |
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 PhysicMaterial to the collider. |
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 |
|---|---|
ApplyCollisionMatrix |
Applies a custom CollisionLayerMatrix to the global physics settings. |
SetGravityVector |
Sets the global gravity vector. |
SetPhysicsIterations |
Configures solver iteration counts. |
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.
Events¶
PhysicsEventRelay¶
A MonoBehaviour that broadcasts Unity's physics callbacks as C# events. Add it to any GameObject that needs to be monitored.
The relay exposes 3D and 2D events:
| Event | Callback |
|---|---|
CollisionEntered / CollisionExited |
OnCollisionEnter / OnCollisionExit |
TriggerEntered / TriggerExited |
OnTriggerEnter / OnTriggerExit |
CollisionEntered2D / CollisionExited2D |
OnCollisionEnter2D / OnCollisionExit2D |
TriggerEntered2D / TriggerExited2D |
OnTriggerEnter2D / OnTriggerExit2D |
PhysicsEvent¶
A serializable IEvent implementation that monitors a PhysicsEventRelay. Configure the event type, layer mask filter, and tag filter in the Inspector.
// 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 |
SignalType 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.
JointMeasurer¶
A measurement bundle that resolves a Joint through a SmartJoint field and runs all listed measurements against it each tick, writing results into Data Storage. Plug it into a DataStorageSetter entry alongside other measurer types.
| Field | Description |
|---|---|
target |
SmartJoint — resolves the joint to measure. |
measurements |
List of IJointMeasurement entries. Each writes to Data Storage under its own Key. |
Joint Measurements¶
| Measurement | Output | Description |
|---|---|---|
HingeAngleMeasurement |
float | Current angle of a HingeJoint relative to its rest pose. |
HingeAngularVelocityMeasurement |
float | Angular velocity of a HingeJoint's motor. |
JointDistanceMeasurement |
float | World-space distance between the joint's anchor and its connected anchor. Detects stretch on spring/configurable joints. |
JointForceMeasurement |
float | Magnitude of the force currently applied by the joint. |
JointTorqueMeasurement |
float | Magnitude of the torque currently applied by the joint. |
ConfigurableJointTwistMeasurement |
float | Twist angle of a ConfigurableJoint around its primary axis. |
ConfigurableJointSwing1Measurement |
float | Swing angle of a ConfigurableJoint around its secondary axis. |
ConfigurableJointSwing2Measurement |
float | Swing angle of a ConfigurableJoint around its tertiary axis. |
Each measurement supports an optional modifier chain (smoothing, clamping) and a configurable execution frequency. Pair with a Float Threshold or Float Range reaction on the same Key to fire processes when values cross a boundary.
Raycasting¶
Raycaster¶
A serializable raycasting utility that encapsulates ray source, layer mask, max distance, trigger handling, caching, and optional batch processing.
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
// Use a Raycaster in your own systems
var raycaster = new Raycaster();
if (raycaster.Cast(out RaycastHit hit))
{
Debug.Log($"Hit {hit.collider.name} at {hit.point}");
}
Sharing raycasters: Use RaycasterValue for inline references or RaycasterValueAsset (ScriptableObject) to share a single raycaster configuration across multiple components.
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). Raycasters 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. |
TriggerDetectionStrategy |
Listens to a PhysicsEventRelay for physics enter/exit callbacks. Pick whether to detect triggers only, colliders only (ignore triggers), or both. Registers both 2D and 3D variants automatically; supports layer mask filtering. |
// Configure a trigger-based detector in the Inspector
[SerializeReference] [JungleClassSelection]
private IDetectionStrategy detection = new TriggerDetectionStrategy();
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. |
CollisionLayerMatrix¶
A serializable representation of Unity's 32x32 layer collision matrix. Snapshot the current physics settings with FromPhysicsSettings() and restore them with ApplyToPhysics().