Skip to content

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:

  1. Target — where should it go?
  2. Modifiers — what should adjust the path on the way?
  3. 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 DirectTransformOperation on 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:

  1. In the operation, find the Target field.
  2. Click the type selector. The current type is Transform Target (or similar — concrete name shown in the picker).
  3. To redirect the destination, pick Transform Target and 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.

  1. Find the Modifiers list inside the transform operation.
  2. Click + to add an entry.
  3. 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:

  1. + in the Modifiers list.
  2. Pick Axis Lock (under Constraints).
  3. 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.

  1. Select DestinationPoint again and open the Attaching tab.
  2. In its process, replace the DirectTransformOperation with a Physics Transform Operation.
  3. 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):

  1. Add a Transformer to a GameObject.
  2. Its Entries list takes TransformerEntry items — subject + root (the operation that runs on that subject).
  3. Set root to 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.

  1. Add a BatchTransformPipelineManager somewhere in the scene.
  2. On each AttachmentPoint that needs batch handling, replace its inline transform operation with a BatchTransformOperation that submits the subject to the manager.
  3. 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