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
Vector3value once - Works with any
ISettableVector3Valueincluding transform positions
ConstrainVector3Process - Continuous position constraint application.
- Continuously constrains a
Vector3value while active - Compatible value types:
TransformWorldPositionValue- constrain transform world positionTransformLocalPositionValue- constrain transform local positionVector3ValueComponent- constrain a serialized Vector3
updateInterval- update rate (0 = every frame)- Exposes
GetProximityToLimit()andModulateLerpSpeed(float)for external systems
Rotation Constraint Operations¶
ConstrainQuaternionProcess - Continuous rotation constraint application.
- Continuously constrains a
Quaternionvalue while active - Compatible value types:
TransformWorldRotationValue- constrain transform world rotationTransformLocalRotationValue- constrain transform local rotationQuaternionValueComponent- constrain a serialized Quaternion
updateInterval- update rate (0 = every frame)- Exposes
GetRotationProximityToLimit()andModulateLerpSpeed(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:
- Add a position constraint (e.g.,
PlaneConstraint,BoundsConstraint,CompositePositionConstraint) - 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:
- DragTarget computes target position/rotation
- DragTargetModifiers modify the target (springs, snapping, etc.)
- DragApplier applies target to the transform
- 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
LateUpdateto run after physics andDragApplier - Composite constraints apply each sub-constraint in sequence (O(n) complexity)
- Use
updateIntervalin process constraints to reduce evaluation frequency if needed - Position and rotation constraint processes only run while the object is being dragged