Runtime Transform Handles for Unity

June 11, 2026 · View on GitHub

Icon

Unity 2021.3+ License: MIT Latest Release

About

Unity Runtime Transform Handles is a powerful tool that allows developers to transform objects at runtime using a set of intuitive and professional gizmos. Ideal for building modding tools, runtime editors, or games that require object manipulation, this plugin provides multiple object selection, changeable origin points, auto-scaling handles, configurable snapping, and a full event system.

Features

  • Position, Rotation, and Scale handles
  • Multiple object selection and manipulation
  • Changeable origin points (pivot/center)
  • World and Local coordinate space support
  • Configurable snapping for precise transformations
  • Auto-scaling handles based on camera distance
  • Customizable keyboard shortcuts via Settings asset
  • Event system for handle interactions
  • Works with both Legacy Input Manager and New Input System out of the box

Video Demo

Video

Browser Demo (WebGL)

Try it in your browser

Requirements

  • Unity 2021.3 or higher.
  • Render pipeline: Built-in and URP (the handle shaders ship both SubShaders, auto-selected). URP is not a dependency: the URP SubShader is compiled only when com.unity.render-pipelines.universal 12.1.0+ is installed (via PackageRequirements); Built-in projects render via the Built-in SubShader with no extra packages. HDRP is not supported out of the box.
  • Input: Works with the Legacy Input Manager out of the box; uses the New Input System automatically when com.unity.inputsystem is present and enabled (no setup required).

Upgrading from 1.x? 2.0.0 is a breaking release — see the migration guide. Upgrading from 2.x? No code changes required — 3.0.0 shipped no breaking changes (the major bump was a release-automation artifact, corrected in 3.0.1).

Installation

  1. Open the Package Manager from Window > Package Manager
  2. Click the "+" button > Add package from git URL
  3. Enter the following URL:
    https://github.com/manaporkun/UnityRuntimeTransformHandles.git#upm
    

Option 2: Manual Installation

Open Packages/manifest.json and add the following to the dependencies block:

{
    "dependencies": {
        "com.orkunmanap.runtime-transform-handles": "https://github.com/manaporkun/UnityRuntimeTransformHandles.git#upm"
    }
}

Option 3: Specific Version

To install a specific version, append the version tag:

{
    "dependencies": {
        "com.orkunmanap.runtime-transform-handles": "https://github.com/manaporkun/UnityRuntimeTransformHandles.git#v3.0.5"
    }
}

Post-Installation Setup

After installing the package, set up the required layer:

  1. Go to Tools > Transform Handles > Setup Layer
  2. This creates the "TransformHandle" layer needed for handle raycasting

Quick Start

Basic Usage

using TransformHandles;
using UnityEngine;

public class SimpleExample : MonoBehaviour
{
    private TransformHandleManager _manager;

    void Start()
    {
        _manager = TransformHandleManager.Instance;
    }

    void CreateHandleForObject(Transform target)
    {
        // Create a handle for a single object
        Handle handle = _manager.CreateHandle(target);

        // Subscribe to events. handle.Pivot is the manipulation pivot (the group's ghost);
        // handle.Targets are the actual objects being manipulated.
        handle.OnInteractionStartEvent += _ => Debug.Log("Started manipulating: " + target.name);
        handle.OnInteractionEndEvent   += _ => Debug.Log("Finished manipulating: " + target.name);
    }
}

Multiple Object Selection

// Create a handle for multiple objects
List<Transform> targets = new List<Transform> { obj1, obj2, obj3 };
Handle handle = _manager.CreateHandleFromList(targets);

// Add more targets to an existing handle
_manager.AddTarget(newTarget, handle);

// Remove a target from a handle
_manager.RemoveTarget(targetToRemove, handle);

Changing Handle Properties

// Change handle type
TransformHandleManager.ChangeHandleType(handle, HandleType.Position);
TransformHandleManager.ChangeHandleType(handle, HandleType.Rotation);
TransformHandleManager.ChangeHandleType(handle, HandleType.Scale);
TransformHandleManager.ChangeHandleType(handle, HandleType.All);

// Change coordinate space
_manager.ChangeHandleSpace(handle, Space.World);
_manager.ChangeHandleSpace(handle, Space.Self);

// Configure snapping
handle.PositionSnap = new Vector3(0.5f, 0.5f, 0.5f);
handle.RotationSnap = 15f;
handle.ScaleSnap = new Vector3(0.1f, 0.1f, 0.1f);

Settings Asset (Optional)

Create a settings asset to customize shortcuts, defaults, and highlight color:

  1. Assets > Create > Transform Handles > Settings
  2. Assign to TransformHandleManager.Settings in Inspector or via code:
TransformHandleManager.Instance.Settings = mySettings;

If no settings asset is assigned, the manager uses its serialized field values.

Blocking Interaction Over UI (opt-in)

Optionally, a handle interaction can be prevented from starting while the pointer is over a uGUI element, so clicking a button or panel above the scene does not begin a drag (an in-progress interaction is never interrupted; touch uses the active finger). It is off by default so it never silently changes input behavior. Requires an EventSystem and the uGUI package; projects without uGUI are unaffected. Enable in the Inspector or via code, and override IsPointerOverUI() for a non-uGUI UI stack:

TransformHandleManager.Instance.BlockWhenPointerOverUI = true;

Default Keyboard Shortcuts

KeyAction
WPosition mode
ERotation mode
RScale mode
AAll modes (Position + Rotation + Scale)
XToggle World/Local space
ZToggle Pivot/Center origin

Samples

The package ships an importable demo:

  1. Open Window > Package Manager and select Runtime Transform Handles.
  2. Open the Samples tab and import Runtime Transform Handles Demo.
  3. Open Assets/Samples/Runtime Transform Handles/<version>/Runtime Transform Handles Demo/RuntimeTransformHandlesDemo.unity and enter Play mode.

The demo spawns its own targets and exercises every handle type, axis mask, coordinate space, snapping mode, multi-object grouping, auto-scaling, and the interaction event system through an on-screen control panel (see the sample's own README for the controls table). The imported copy under Assets/Samples/ is regenerable — it can be deleted and reimported at any time.

Package Structure

Packages/com.orkunmanap.runtime-transform-handles/
├── Editor/
│   └── TransformHandleLayerSetup.cs        # Layer setup menu item
├── Runtime/
│   ├── Materials/                           # Handle materials
│   ├── Models/                              # Mesh assets (cone, torus, tube)
│   ├── Prefabs/                             # Handle and Ghost prefabs
│   ├── Scripts/
│   │   ├── Colliders/                       # Runtime mesh collider controllers
│   │   ├── Enums/                           # HandleType, HandleAxes, SnappingType, Origin
│   │   ├── HandleComponents/
│   │   │   ├── HandleBase.cs                # Abstract base for axis components
│   │   │   ├── Position/                    # PositionHandle, PositionAxis, PositionPlane
│   │   │   ├── Rotation/                    # RotationHandle, RotationAxis
│   │   │   └── Scale/                       # ScaleHandle, ScaleAxis, ScaleGlobal
│   │   ├── Utils/                           # InputWrapper, MathUtils, MeshUtils, SnapUtils, Singleton
│   │   ├── Ghost.cs                         # Pivot point for manipulation
│   │   ├── Handle.cs                        # Per-target handle controller
│   │   ├── TransformGroup.cs                # Multi-object grouping
│   │   ├── TransformHandleManager.cs        # Central singleton manager
│   │   └── TransformHandleSettings.cs       # ScriptableObject settings
│   └── Shader/                              # Handle and origin shaders (Built-in + URP)
├── Tests/                                   # EditMode + PlayMode test assemblies
├── Samples~/Demo/                           # Importable demo sample (Package Manager)
├── Documentation~/                          # index.md (architecture + API) + migration guide
└── package.json

Documentation

Main Components

TransformHandleManager

Central manager for all transform handles in the scene. Handles creation, destruction, and interaction with transform handles.

Key Methods:

  • CreateHandle(Transform target) - Creates a handle for a single object
  • CreateHandleFromList(List<Transform> targets) - Creates a handle for multiple objects
  • AddTarget(Transform target, Handle handle) - Adds an object to an existing handle
  • RemoveTarget(Transform target, Handle handle) - Removes an object from a handle
  • RemoveHandle(Handle handle) - Removes a handle
  • DestroyAllHandles() - Destroys all handles
  • ChangeHandleType(Handle handle, HandleType type) - Changes the handle type
  • ChangeHandleSpace(Handle handle, Space space) - Changes the coordinate space

Handle

Main handle component that manages transform manipulation through position, rotation, and scale handles.

Properties:

  • target - The transform being manipulated
  • type - Current handle type (Position, Rotation, Scale, or combinations)
  • space - Coordinate space (Self or World)
  • axes - Active axes (X, Y, Z, or combinations)
  • positionSnap, rotationSnap, scaleSnap - Snapping values
  • autoScale - Enable/disable auto-scaling based on camera distance

Events:

  • OnInteractionStartEvent - Fired when interaction begins
  • OnInteractionEvent - Fired during interaction
  • OnInteractionEndEvent - Fired when interaction ends
  • OnHandleDestroyedEvent - Fired when handle is destroyed

Ghost

Represents an empty transform object that serves as the pivot point for handle manipulation. The Ghost transform is instantiated when a handle is created and updates its position, rotation, and scale based on user input.

TransformGroup

Groups and transforms multiple Unity Transform objects together. Contains methods to add/remove transforms and update the group's position, rotation, and scale collectively.

Handle Types

public enum HandleType
{
    Position,
    Rotation,
    Scale,
    PositionRotation,
    PositionScale,
    RotationScale,
    All
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes using Conventional Commits:
    • feat: add new feature (triggers minor version bump)
    • fix: resolve bug (triggers patch version bump)
    • feat!: breaking change (triggers major version bump)
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Releases are automated via GitHub Actions based on commit messages.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Support

If you encounter any issues or have questions, please open an issue on GitHub.