Skip to content

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.

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

public interface IPhysicsOperation : IOperation
{
    void Begin(Rigidbody rb, Action onComplete);
}

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.

Add Component > Jungle > Events > Physics Event Relay

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, OnCollisionExit
  • OnTriggerEnter, OnTriggerExit
  • OnCollisionEnter2D, OnCollisionExit2D
  • OnTriggerEnter2D, 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.

Add Component > Jungle > Events > Joint Break Signal Source
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_ENABLED is defined, raycasts are submitted to the RaycastPerformanceManager for 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().