Skip to content

Spatial Constraints System

Limit where objects can move and how they can rotate - planes, bounds, spheres, orbits, grids - with configurable boundary behaviors.


Overview

Constraints keep objects within the boundaries you define. Pick a shape (plane, box, sphere, cylinder, line, orbit, grid, or snap points), assign it to an object, and the system clamps position and rotation every frame. Near the edges, you can choose what happens: a hard stop, a gradual slowdown, an elastic bounce, or smooth damping. Combine multiple constraints in a composite for layered rules.

The constraint system works standalone or integrates directly with Octoputs drag-and-drop operations, applying limits automatically while an object is being dragged with zero overhead when idle.

  • Position constraints - limit where objects can be positioned
  • Rotation constraints - limit how objects can be rotated
  • Limit behaviors - control what happens near constraint boundaries (slow down, elastic, damped)
  • Drag integration - automatic constraint application during Octoputs drag operations

Core Interfaces

Under the hood, constraints implement two interfaces. You rarely need to use these directly - the Inspector class picker handles selection - but they are useful when writing custom constraints.

IPositionConstraint

Defines constraints that limit position:

Method Description
ConstrainPosition(Vector3) Apply constraint to a position
GetProximityToLimit(Vector3) Get distance to boundary (0 = at limit, 1 = far from limit)
ApplyLimitToLerpSpeed(Vector3, float) Modify lerp speed based on proximity to the limit

IRotationConstraint

Defines constraints that limit rotation:

Method Description
ConstrainRotation(Quaternion) Apply constraint to a rotation
GetRotationProximityToLimit(Quaternion) Get distance to angular boundary (0 = at limit, 1 = far)
ApplyLimitToLerpSpeed(Quaternion, float) Modify lerp speed based on proximity to the limit

Limit Behaviors

Control how constraints behave when approaching boundaries.

LimitBehaviour Enum

Value Effect
HardStop Instant stop at boundary, no special behavior
SlowDown Progressively reduce lerp/movement speed as approaching limit
Elastic Quadratic falloff for a smoother elastic feel near boundary
Damped Exponential falloff for a damping effect near boundary

Common Parameters

All constraints that support limit behaviors expose these fields:

Field Default Description
limitBehaviour HardStop The behavior to apply near the boundary
limitTransitionDistance / limitTransitionAngle - Distance or angle from the limit where the behavior starts
limitStrength 0.8 How strong the effect is (range 0--1)

Position Constraints

PlaneConstraint

Constrains position to a plane.

Field Description
planePoint Point on the plane (world space)
planeNormal Normal direction of the plane

LineConstraint

Constrains position to an infinite line.

Field Description
linePoint Point on the line (world space)
lineDirection Direction of the line

LineSegmentConstraint

Constrains position to a line segment between two points.

Field Description
startPoint Segment start (world space)
endPoint Segment end (world space)

BoundsConstraint

Constrains position to within an axis-aligned bounding box.

Field Description
center Center of the box (world space)
size Size of the box

SphereConstraint

Constrains position to within or outside a sphere.

Field Description
center Center of the sphere (world space)
radius Radius of the sphere
constrainInside Keep inside (true) or outside (false)

CylinderConstraint

Constrains position to within or outside a cylinder.

Field Description
center Center of the cylinder (world space)
axis Cylinder axis direction
radius Cylinder radius
halfHeight Half-height along axis
constrainInside Keep inside (true) or outside (false)

DistanceConstraint

Constrains position based on distance from a reference point.

Field Description
referencePoint Reference point (world space)
minDistance Minimum allowed distance
maxDistance Maximum allowed distance

CurveConstraint

Constrains position to follow a curve or spline path.

OrbitPositionConstraint

Constrains position to an orbit around a reference point, keeping a fixed distance.

GridSnapPositionConstraint

Snaps position to the nearest point on a regular grid.

AxisLockPositionConstraint

Locks one or more axes of the position, preventing movement along those axes.

SnapPointConstraint

Snaps position to the nearest defined snap point from a set of discrete positions.

CompositePositionConstraint

Combines multiple position constraints in sequence.

Field Description
constraints List of IPositionConstraint to apply in order

Composites apply constraints sequentially

Each constraint in the list receives the output of the previous one. Order matters - place broad constraints (like BoundsConstraint) before fine constraints (like GridSnapPositionConstraint).


Rotation Constraints

RotationConstraint

Constrains rotation to angular limits around each axis.

Field Description
referenceRotation Reference rotation to measure from
maxAngleX / maxAngleY / maxAngleZ Maximum angle deviation per axis (degrees)
constrainX / constrainY / constrainZ Enable constraint per axis

AngleSnapRotationConstraint

Snaps rotation to the nearest angle increment around each axis.

AxisLockRotationConstraint

Locks one or more axes of the rotation, preventing rotation around those axes.

CompositeRotationConstraint

Combines multiple rotation constraints in sequence.

Field Description
constraints List of IRotationConstraint to apply in order

Actions and Processes

Position Constraint Operations

ConstrainVector3Action - One-time position constraint application.

  • Instant action that constrains a Vector3 value once
  • Works with any ISettableVector3Value including transform positions

ConstrainVector3Process - Continuous position constraint application.

  • Continuously constrains a Vector3 value while active
  • Compatible value types:
    • TransformWorldPositionValue - constrain transform world position
    • TransformLocalPositionValue - constrain transform local position
    • Vector3ValueComponent - constrain a serialized Vector3
  • updateInterval - update rate (0 = every frame)
  • Exposes GetProximityToLimit() and ModulateLerpSpeed(float) for external systems

Rotation Constraint Operations

ConstrainQuaternionProcess - Continuous rotation constraint application.

  • Continuously constrains a Quaternion value while active
  • Compatible value types:
    • TransformWorldRotationValue - constrain transform world rotation
    • TransformLocalRotationValue - constrain transform local rotation
    • QuaternionValueComponent - constrain a serialized Quaternion
  • updateInterval - update rate (0 = every frame)
  • Exposes GetRotationProximityToLimit() and ModulateLerpSpeed(float) for external systems

Value Types for Transforms

Type Purpose
TransformWorldPositionValue / TransformLocalPositionValue ISettableVector3Value implementations for transform positions
TransformWorldRotationValue / TransformLocalRotationValue ISettableQuaternionValue implementations for transform rotations

Usage with Octoputs DraggableObject

DraggableObject supports direct constraint application configured in the Inspector:

[SerializeReference]
IPositionConstraint positionConstraint;

[SerializeReference]
IRotationConstraint rotationConstraint;

Setup in Inspector:

  1. Add a position constraint (e.g., PlaneConstraint, BoundsConstraint, CompositePositionConstraint)
  2. Add a rotation constraint (optional, e.g., RotationConstraint)

The constraints are automatically:

  • Registered when drag begins - callback registered with ConstraintUpdateManager
  • Applied every LateUpdate during drag - directly to the dragged transform
  • Unregistered when drag ends - callback removed from ConstraintUpdateManager

Zero overhead when idle

Constraints only run while the object is being dragged. There is no per-frame cost for inactive objects.


Integration with the Drag System

The constraint system integrates with the Octoputs drag pipeline:

  1. DragTarget computes target position/rotation
  2. DragTargetModifiers modify the target (springs, snapping, etc.)
  3. DragApplier applies target to the transform
  4. Constraints clamp the final position/rotation (DraggableObject constraints)

This layered approach allows for complex behaviors like:

  • Dragging along a plane with elastic boundaries
  • Following a path with distance limits
  • Rotating with angular limits and slowdown near boundaries

Examples

Constrain to a Plane with Slowdown

In the DraggableObject Inspector, under "Constraints":

Position Constraint:
  Type: PlaneConstraint
  Plane Point: (0, 0, 0)
  Plane Normal: (0, 1, 0)
  Limit Behaviour: SlowDown
  Limit Transition Distance: 0.5
  Limit Strength: 0.5

Constrain Rotation with Damping

Rotation Constraint:
  Type: RotationConstraint
  Reference Rotation: (0, 0, 0, 1)   # 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

Combine Multiple Constraints

Use a CompositePositionConstraint:

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

All constraints in the composite are applied in sequence during drag.


Centralized Update - ConstraintUpdateManager

All active constraints are managed by a single ConstraintUpdateManager singleton:

Feature Description
Single update point One LateUpdate call for all active constraints
Automatic cleanup Callbacks are safely removed when processes end
Error isolation An exception in one constraint does not affect others
Debug support GetRegisteredCallbackCount() for monitoring active constraints
Persistent Marked DontDestroyOnLoad and HideAndDontSave

Performance Notes

  • Constraints are evaluated in LateUpdate to run after physics and DragApplier
  • Composite constraints apply each sub-constraint in sequence (O(n) complexity)
  • Use updateInterval in process constraints to reduce evaluation frequency if needed
  • Position and rotation constraint processes only run while the object is being dragged