Skip to content

Constraints

Limit where transforms can move and how they can rotate — planes, bounds, spheres, cylinders, lines, orbits, grids, snap points, axis locks — with optional soft-edge behaviours near the boundary.


Overview

Constraints clamp a transform's position and rotation against the shapes you list. Pick a shape, attach it to one of the entry points below, and the system clamps every frame the entry point is active. Near the edges, you choose what happens: a hard stop, a gradual slowdown, an elastic bounce, or smooth damping. Composite constraints layer multiple rules in sequence.

Namespace: Octoputs.Constraints. Assembly: Octoputs.

  • Position constraints — limit where a transform can be.
  • Rotation constraints — limit how a transform can be oriented.
  • Limit behaviours — choose what happens approaching a boundary.
  • Two entry points — a standalone Constrainer component or drag-pipeline modifiers.

Entry points

The same constraint instances plug into three different surfaces. Pick the one that matches what's driving the transform.

Constrainer component

A MonoBehaviour you drop on a GameObject. Hosts a list of position and rotation constraints and applies them every LateUpdate while it is active. Active/inactive is decided by an IExecutionFrame (the standard Jungle lifecycle picker), so the constraining window can be tied to OnEnable/OnDisable, an attachment cycle, an event, or external Begin()/End() calls.

Field Default Description
target null (self) Transform to constrain. Leave empty to constrain this GameObject.
space World Apply position/rotation in world or local space.
positionConstraints empty Applied in order each LateUpdate. Empty = position passthrough.
rotationConstraints empty Applied in order each LateUpdate. Empty = rotation passthrough.

Use this whenever you want a transform constrained outside of a drag flow — patrol zones, UI bounds, persistent enclosures, gameplay boundaries triggered by lifecycle or events.

Drag pipeline modifiers

Inside an Octoputs drag transform pipeline, three modifiers expose the constraint system:

  • PositionConstraintModifier — clamps the dragged target's position.
  • RotationConstraintModifier — clamps the dragged target's rotation.
  • OrbitConstraintModifier — combines OrbitPositionConstraint with optional face-the-center rotation.

These run only while a drag is active and only on the dragged object.


Limit behaviours

Every constraint that derives from PositionConstraintBase / RotationConstraintBase exposes the same three knobs that shape what happens near the boundary.

Field Effect
LimitBehaviour.HardStop Snap to the boundary, no easing.
LimitBehaviour.SlowDown Linear lerp from limitStrength to 1 inside the transition band.
LimitBehaviour.Elastic Quadratic falloff inside the transition band.
LimitBehaviour.Damped Cubic falloff inside the transition band.
limitTransitionDistance / limitTransitionAngle How far from the boundary the soft behaviour begins.
limitStrength Multiplier applied right at the boundary (0 = stalled, 1 = no effect).

The computed factor is consumed by ApplyLimitToLerpSpeed, which the modifiers call to scale their interpolation speed as the value approaches a limit.


Core interfaces

public interface IPositionConstraint
{
    Vector3 ConstrainPosition(Vector3 position);
    float   GetDistanceToLimit(Vector3 position);
}

public interface IRotationConstraint
{
    Quaternion ConstrainRotation(Quaternion rotation);
    float      GetDistanceToLimit(Quaternion rotation);
}

PositionConstraintBase and RotationConstraintBase implement the limit-behaviour machinery; custom constraints should usually inherit from them rather than implement the bare interface.


Position constraints

Type Shape
PlaneConstraint Project onto an infinite plane.
LineConstraint Project onto an infinite line.
LineSegmentConstraint Project onto a finite line segment.
BoundsConstraint Clamp inside an axis-aligned box.
SphereConstraint Clamp inside or outside a sphere.
CylinderConstraint Clamp inside or outside a cylinder.
DistanceConstraint Min/max distance shell from a reference point.
OrbitPositionConstraint Sphere with optional plane intersection — orbit around a point at fixed radius.
CurveConstraint Project onto a Jungle ICurve3D (path/spline).
GridSnapPositionConstraint Snap to a regular 3D grid.
SnapPointConstraint Snap to the nearest of a list of discrete points.
AxisLockPositionConstraint Lock selected world or local axes.
NoPositionConstraint Passthrough — returns the input position unchanged. Useful as a placeholder in composites or conditionals.
CompositePositionConstraint Apply a sequence of IPositionConstraints in order.

Composites

CompositePositionConstraint:
  Constraints:
    [0] BoundsConstraint     # keep within box
    [1] DistanceConstraint   # keep min/max distance from point

The output of each constraint feeds the next. Order matters — place broad constraints (e.g. BoundsConstraint) before fine constraints (e.g. GridSnapPositionConstraint).


Rotation constraints

Type Shape
RotationConstraint Per-axis Euler clamping relative to a reference rotation.
AngleSnapRotationConstraint Snap to angle increments per axis.
AxisLockRotationConstraint Lock selected Euler axes to a reference rotation.
NoRotationConstraint Passthrough — returns the input rotation unchanged. Useful as a placeholder in composites or conditionals.
CompositeRotationConstraint Apply a sequence of IRotationConstraints in order.

Examples

Constrain a Transform to a plane (no drag)

Drop Constrainer on the GameObject:

Constrainer:
  Target: <leave empty — uses this GameObject>
  Space: World
  Position Constraints:
    [0] PlaneConstraint
        Plane Point: (0, 0, 0)
        Plane Normal: (0, 1, 0)
        Limit Behaviour: SlowDown
        Limit Transition Distance: 0.5
        Limit Strength: 0.5

Switch the execution frame to drive the constraining window from anything you like — an attachment cycle, an event, or external Begin()/End() calls.

Constrain a dragged object to a sphere

In the drag transform pipeline, add a PositionConstraintModifier with a SphereConstraint:

PositionConstraintModifier:
  Position Constraint:
    Type: SphereConstraint
    Center: (0, 1, 0)
    Radius: 2
    Constrain Inside: true
    Limit Behaviour: Damped
    Limit Transition Distance: 0.3

Rotate within angular limits

RotationConstraintModifier:
  Rotation Constraint:
    Type: RotationConstraint
    Reference Rotation: identity
    Max Angle X: 45
    Max Angle Y: 90
    Max Angle Z: 0
    Constrain X / Y / Z: true / true / false
    Limit Behaviour: Damped
    Limit Transition Angle: 15

Performance notes

  • All Constrainer instances tick from the central UpdateManager LateUpdate pass — no per-component MonoBehaviour overhead.
  • Composites are O(n) in their inner-constraint count. Keep frequently-evaluated composites short.
  • Constrainer and the operation surfaces only run while their lifecycle is active; idle objects cost nothing.
  • Position and rotation passes are skipped entirely when the corresponding list is empty.