Skip to content

Instantly share code, notes, and snippets.

@wtrebella
Last active August 22, 2022 06:15
Show Gist options
  • Save wtrebella/dbdf882c956dfe1cbc532f3cacf4653d to your computer and use it in GitHub Desktop.
Save wtrebella/dbdf882c956dfe1cbc532f3cacf4653d to your computer and use it in GitHub Desktop.
This is a Unity menu item script that allows you to easily apply a transform's values to its direct children
/*
Demo video: https://i.imgur.com/bRlAHT9.mp4
This tool allows you to easily apply a transform's values to its direct children.
For example, say we have a parent object called "Starfield" that holds 100 "Star" game objects as direct children.
The Starfield's rotation is set to (x=0, y=0, z=0), and ideally you'd like to keep it that way (for some whatever reason).
But The Stars are arranged in a certain pattern, and it doesn't look right. You don't want to manually adjust
each individual Star. So you rotate the Starfield object to rotate the entire starfield itself.
Only problem is, the Starfield object no longer has a rotation of (x=0, y=0, z=0).
It's now (x=0, y=0, z=67.32334f) or whatever.
One way to solve this is by manually dragging all the Stars out of the Starfield game object,
setting the Starfield object's rotation to (x=0, y=0, z=0), then manually dragging the Stars
back onto the Starfield game object, reparenting them to the now-rotationally-applied Starfield.
This tool allows you to apply a transform in the following ways:
1. Position
2. Rotation
3. Scale
4. Rotation & Scale
5. Transform (i.e. apply Position, Rotation, and Scale)
One caveat: applying non-uniform scales can have undesired effects
*/
using System.Linq;
using UnityEngine;
using UnityEditor;
public class ApplyTransformMenuItem : MonoBehaviour
{
const string PATH_BASE = "Tools/Whit's Stuff/";
const string APPLY_POSITION_PATH = PATH_BASE + "Apply Position";
const string APPLY_ROTATION_PATH = PATH_BASE + "Apply Rotation";
const string APPLY_SCALE_PATH = PATH_BASE + "Apply Scale";
const string APPLY_ROTATION_AND_SCALE_PATH = PATH_BASE + "Apply Rotation and Scale";
const string APPLY_TRANSFORM_PATH = PATH_BASE + "Apply Transform";
#region MenuItems
// Position
[MenuItem(APPLY_POSITION_PATH)]
static void ApplyPosition()
{
ApplyTransformInternal(Selection.activeTransform, true, false, false);
}
[MenuItem(APPLY_POSITION_PATH, true)]
static bool ValidateApplyPosition() { return ValidateSelection(); }
// Rotation
[MenuItem(APPLY_ROTATION_PATH)]
static void ApplyRotation()
{
ApplyTransformInternal(Selection.activeTransform, false, false, true);
}
[MenuItem(APPLY_ROTATION_PATH, true)]
static bool ValidateApplyRotation() { return ValidateSelection(); }
// Scale
[MenuItem(APPLY_SCALE_PATH)]
static void ApplyScale()
{
ApplyTransformInternal(Selection.activeTransform, false, true, false);
}
[MenuItem(APPLY_SCALE_PATH, true)]
static bool ValidateApplyScale() { return ValidateSelection(); }
// Rotation & Scale
[MenuItem(APPLY_ROTATION_AND_SCALE_PATH)]
static void ApplyRotationAndScale()
{
ApplyTransformInternal(Selection.activeTransform, false, true, true);
}
[MenuItem(APPLY_ROTATION_AND_SCALE_PATH, true)]
static bool ValidateApplyRotationAndScale() { return ValidateSelection(); }
// Transform
[MenuItem(APPLY_TRANSFORM_PATH)]
static void ApplyTransform()
{
ApplyTransformInternal(Selection.activeTransform, true, true, true);
}
[MenuItem(APPLY_TRANSFORM_PATH, true)]
static bool ValidateApplyTransform() { return ValidateSelection(); }
#endregion
static void ApplyTransformInternal(Transform transform, bool position, bool scale, bool rotation)
{
GameObject root = transform.gameObject;
GameObject[] children =
Enumerable.Range(0, root.transform.childCount)
.Select(i => root.transform.GetChild(i).gameObject)
.ToArray();
Undo.RegisterFullObjectHierarchyUndo(root, "Apply Transform");
for (int i = 0; i < children.Length; i++)
{
Transform child = children[i].transform;
child.SetParent(null, true);
}
if (position)
{
root.transform.localPosition = Vector3.zero;
}
if (scale)
{
root.transform.localScale = Vector3.one;
}
if (rotation)
{
root.transform.rotation = Quaternion.identity;
}
for (int i = 0; i < children.Length; i++)
{
Transform child = children[i].transform;
child.SetParent(root.transform, true);
}
}
static bool ValidateSelection()
{
return Selection.activeTransform != null && Selection.activeTransform.childCount > 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment