Tutorial: Transform Operations¶
Control how objects move — add bounce, snap to a grid, avoid walls, or make objects feel heavy. Instead of teleporting from A to B, you'll make objects move with personality.
By the end you'll have a cube that springs toward its slot with overshoot, stays locked to a horizontal plane, and slides around obstacles instead of clipping through them.
Prerequisites: Complete Your First Drag and Drop. You should have a Cube + DestinationPoint with a working attach.
How Movement Works in Octoputs¶
Every time an object attaches to a slot, something moves it into position. That something is a transform operation — an IProcess with three internal stages:
- Target — where should it go?
- Modifiers — what should adjust the path on the way?
- Applier — how should the final position be written? (Direct transform write, physics force, joint constraint, …)
flowchart LR
T["Target<br/>(destination)"] --> M1["Modifier 1"] --> M2["Modifier 2"] --> M3["..."] --> A["Applier"]
Each piece is independent and swappable.
Operations vs the Transformer Component¶
You can author transform operations in two places:
- Inline on an AttachmentPoint — drop them into its Attaching / Detaching processes. This is what new AttachmentPoints do out of the box: their default attaching process contains a
DirectTransformOperationon the held object. - On a Transformer component — when you want to drive several subjects together, or compose multi-step operations (
Sequence,Parallel) under a shared execution frame.
This tutorial works on the AttachmentPoint's attaching process. The same operations apply to the Transformer.
1. Look at the Default Operation¶
Select DestinationPoint in the Hierarchy. In its AttachmentPoint inspector, open the Attaching tab. You'll see a process that contains, among other things, a Direct Transform Operation with the default pivot (AttachablePreferredTransformPivot).
That's the snap-to-position behaviour. We'll customize it.
Why an Operation and not a separate component?
Transform operations are IProcess items hosted inside command lists. They begin when their host begins, end when their host ends, and can be composed (Sequence, Parallel) like any other process. That's the same composition pattern used everywhere in Jungle, so anything you learn here applies to operation lists in commands, reactor bodies, agent preparation processes, and so on.
2. Set the Destination¶
The target answers the question where should the object end up?
The default DirectTransformOperation on AttachmentPoint comes with a target that already resolves to this point. If you want to override:
- In the operation, find the Target field.
- Click the type selector. The current type is
Transform Target(or similar — concrete name shown in the picker). - To redirect the destination, pick
Transform Targetand drag any Transform reference into it.
Other target types
Octoputs ships targets for many shapes of "where to go":
RayHitTransformTarget— follow a raycast hit point on a surface.LerpedTransformTarget— lerp from current to a destination over a duration.ShapeTraversalTransformTarget— travel along a shape (line, arc, circle, or a 3D curve) at a set speed.BlendedTransformTarget— interpolate between two targets using a weight.SequenceTransformTarget— step through a list of targets in order.CompositeTransformTarget— take position from one target and rotation from another.
See the API Reference for the full list.
3. Add Bounce with a Spring Modifier¶
Modifiers sit between the target and the applier, adjusting the computed position before it's written. Let's make the cube overshoot its target and spring back.
- Find the Modifiers list inside the transform operation.
- Click + to add an entry.
- From the type selector, choose Spring (under the Physics category).
| Field | Tuning hint |
|---|---|
| Spring Strength | 1200 is snappy; 300 feels lazy. |
| Damping | 20 settles fast; 8 lets it bounce. |
| Max Spring Range | Clamps how far the spring will stretch. |
| Max Velocity / Acceleration | Caps for stability. |
Try Spring Strength = 300, Damping = 8 for a visible overshoot. Increase Damping to kill bounce, or raise Spring Strength for a snappier feel.
Rule of thumb
Strength ≈ 10× Damping → visible bounce. Strength ≈ 60× Damping → tight follow, almost no overshoot.
Press Play and re-attach. The cube now springs into the slot.
4. Lock an Axis¶
Modifiers execute top to bottom. Each receives the previous one's output. You can stack as many as you want.
Add a second modifier:
- + in the Modifiers list.
- Pick Axis Lock (under Constraints).
- Check Lock Y.
The chain is now:
flowchart LR
T["TransformTarget"] --> S["SpringModifier"] --> A["AxisLockModifier"] --> P["Applier (Direct)"]
Play. The cube springs in X and Z, but Y is locked.
Order matters
Swap the order — AxisLock first, then Spring — and the spring reintroduces Y motion after the lock. Always place constraints after dynamic modifiers when the constraint should have the final word.
5. Use Physics Instead of Direct Writes¶
So far the operation writes the transform directly each frame. For objects that need to push other things, respect gravity, or settle against world geometry, swap the operation type itself — not just a modifier.
- Select DestinationPoint again and open the Attaching tab.
- In its process, replace the
DirectTransformOperationwith a Physics Transform Operation. - Configure the target the same way as before.
Rigidbody required
The cube needs a Rigidbody. If it doesn't have one, add it now (Add Component → Physics → Rigidbody).
Key fields on PhysicsTransformOperation:
| Setting | What it does |
|---|---|
| Use Velocity Based | On: assigns linearVelocity directly. Off: applies forces. |
| Spring Strength / Damper | Velocity-mode pull. |
| Movement Force | Force-mode pull. |
| Max Velocity | Cap to prevent runaway. |
| Override Gravity | Disable gravity while running. |
| Freeze Rotation | Lock rotation during movement. |
Use Direct when placement should be pixel-perfect (UI, strategy, editors). Use Physics when the object lives in a physical world and must push, collide, and interact (VR, physics puzzles).
6. Slide Around Obstacles¶
Physics operations get collision response from the Rigidbody. Direct operations don't — they teleport through geometry. To prevent clipping with a direct operation, add a collision modifier.
Switch the operation back to DirectTransformOperation for this step. Add one of:
| Modifier | How it works | Best for |
|---|---|---|
| Depenetration | Uses Physics.ComputePenetration to push out of overlaps. |
General-purpose, physically correct push directions. |
| Surface Slide | Sweeps the bounding box, slides along surfaces on contact. | Smooth surface-following while dragging. |
For this tutorial, pick Surface Slide.
Drop a wall or two between the cube's start position and DestinationPoint. Re-trigger the attach. The cube glides around the wall instead of clipping through it.
Layer mask
Both collision modifiers expose a Layer Mask field. Default is "everything". Restricting to obstacle layers improves performance and avoids accidental self-collisions.
7. Composing Operations: Sequence and Parallel¶
So far we've stacked modifiers inside a single operation. Sometimes you want to stack operations themselves — e.g. "scale up, then move, then scale back".
That's what SequenceTransformOperation and ParallelTransformOperation are for. They're transform operations whose body is a list of child transform operations on the same subject.
To run them, host them on a Transformer component (or replace your AttachmentPoint's attaching process with a sequence):
- Add a Transformer to a GameObject.
- Its Entries list takes
TransformerEntryitems —subject+root(the operation that runs on that subject). - Set
rootto a Sequence Transform Operation and add child operations: scale up, then translate, then scale back.
When the Transformer begins, every entry runs its root in parallel; within a root the Sequence runs children in order. This lets a single component drive scripted multi-step transforms for many subjects.
8. Big Crowds: the Batch Pipeline¶
When you have hundreds of attachables doing the same kind of motion, regular transform operations one-by-one stop being fast enough. Octoputs ships a Burst/Jobs-based batch pipeline as a drop-in.
- Add a BatchTransformPipelineManager somewhere in the scene.
- On each AttachmentPoint that needs batch handling, replace its inline transform operation with a
BatchTransformOperationthat submits the subject to the manager. - Configure the batch modifiers in the manager (Smooth Position, Snap2DGrid, Spring, Oscillator, KinematicsLimiter, AntiJitter, Pivot — the same primitives, Burst-friendly).
The trade-off: batch modifiers are a focused subset of the full modifier catalog. Use it where throughput matters; stay with the regular operations elsewhere.
See BatchTransformPipelineManager.
Modifier Reference¶
Octoputs ships 30+ modifiers across categories. Quick reference — see API Reference for full details.
Constraint and snapping¶
| Modifier | What it does |
|---|---|
AxisLockModifier |
Lock movement on specific axes. |
PositionConstraintModifier |
Clamp position within min/max bounds. |
RotationConstraintModifier |
Clamp rotation within angle limits. |
OrbitConstraintModifier |
Constrain to an orbital path. |
HeightLockModifier |
Lock Y to a fixed height. |
Snap2DGridModifier / Snap3DGridModifier |
Snap to grid. |
Physics and dynamics¶
| Modifier | What it does |
|---|---|
SpringModifier |
Elastic, bouncy motion. |
ElasticBandModifier |
Rubber-band pull-back beyond a threshold. |
MomentumModifier |
Carry inertia after release. |
KinematicsLimiterModifier |
Cap velocity / acceleration. |
Raycast and collision¶
| Modifier | What it does |
|---|---|
DepenetrationModifier |
Push out of overlaps. |
SurfaceSlideModifier |
Sweep + slide along surfaces. |
OBBCollisionAvoidanceModifier |
OBB-based avoidance. |
CameraRaycast2DOffsetModifier |
Offset from a 2D camera raycast. |
OcclusionRayPushModifier |
Cast a ray from the camera to the upstream wanted point; when the path is occluded, push onto the impact surface with a configurable offset. No-op when clear. |
BoundingOffsetFromHitNormalModifier |
Offset from surface using hit normal + object bounds. |
Alignment and orientation¶
| Modifier | What it does |
|---|---|
SurfaceNormalAlignmentModifier |
Align rotation to a surface normal. |
GravityAlignmentModifier |
Align rotation to gravity. |
TiltByVelocityModifier |
Tilt in the direction of motion. |
LookAtModifier |
Face a target point or direction. |
Animation and oscillation¶
| Modifier | What it does |
|---|---|
OscillatorTransformModifier |
Bob / sway while held. |
NoiseOffsetModifier |
Perlin noise wiggle. |
PendulumSwingModifier |
Pendulum swing on pickup. |
Smoothing and filtering¶
| Modifier | What it does |
|---|---|
SmoothPositionModifier / SmoothRotationModifier |
Damped follow. |
AntiJitterModifier |
Suppress micro-jitter. |
Specialized¶
| Modifier | What it does |
|---|---|
PreserveViewRelativeOrientationModifier |
Keep visual angle to camera through perspective. |
InfluenceModifier |
Pull the target toward an influence pose (e.g. a barycenter of Points of Interest). Activation is automatic — fades in while the influence source has a pose, out when it doesn't. |
ScaleByDistanceModifier |
Scale by distance from a reference. |
ConditionalModifier |
Apply a wrapped modifier only when a Condition is true. |
Modifier Blend Factor¶
Every modifier carries a Blend Factor (default 1) — a SmartFloat that lerps between pre-modifier and post-modifier values each frame. 1 = full effect, 0 = passthrough, anywhere between = a partial blend. Wire it to any value source (data storage, slider, observable) to fade modifier effects in and out at runtime.
Next Steps¶
- Restrict which objects accept which slots with Tag-Based Filtering.
- Drive a full robot arm or NPC carrier with AttachingAgent Workflow.
- Add hard spatial limits with a Constrainer.
- Browse every component in the API Reference.