Rotate parent but not child

This is a bit embarrassing. I’m making a game with 2d characters(who isn’t?) and would like to implement some stuff like flocking. This seems to require steering, but I only want to steer(rotate) the parent. I would like the children to not rotate with the parent. Is there an easy way to do this?

I’ve never worked with parent/child relationships, but I’ll throw this out there:
(pseudo-code)

childObject.transform.parent = null;
parentObject.transform.rotate(......)
childObject.transform.parent = parentObject.transform;

Simply, remove the parent-child relationship, rotate the parent, restore the relationship. I have no idea if this will work though. :smile:

2 Likes
private var OrgRotation : Quaternion;
private var OrgPosition : Vector3;

function Start()
{
	OrgRotation = transform.rotation;
	OrgPosition = transform.parent.transform.position - transform.position;
}

function LateUpdate()
{
	transform.rotation = OrgRotation;
	transform.position = transform.parent.position - OrgPosition;
}
2 Likes

Perhaps a little late, but this is one of the top results on google. Below is how to do it. Notice that you set the world rotation of the parent, but the local rotation of the child.

// create the angle with Unity's stupid Quaternion bs
var eulerRot = Quaternion.Euler(0f, 0f, rotation);

// set the rotation of the parent
transform.rotation = eulerRot;

// set the local rotation of the child to the opposite of the parent
child.localRotation = Quaternion.Euler(0f, 0f, -rotation);

Well, as long as we’re necroposting, let’s clear up the advice.

You could actually do either .rotation or .localRotation for the parent.
And in fact, it’s simpler to just set the child’s .rotation to Quaternion.identity (or whatever you want its world rotation to be), which will accomplish the same thing as your code - it makes the engine do the work of inverting the parent’s rotation instead of you having to write the code that way yourself.

var rotation = Quaternion.Euler(0f, 0f, rotation);
transform.rotation = rotation;
child.rotation = Quaternion.identity;

And you should definitely educate yourself on “Unity’s stupid Quaternion bs” because Quaternions are far and away the best way to handle rotations in 3D. Euler angles have a lot of problems. Quaternions are, admittedly, overkill for 2D, but Unity is fundamentally a 3D engine that just happens to also support 2D games.

2 Likes

I’m sticking with 2D games for now, but thanks for the information.

If anyone wants a nice solution to position/rotate/scale the parent without affecting it’s children, including Undo, here you go:

How to use:

  • Position:

  • Select one or multiple child objects in the hierarchy

  • right click it / them

  • select “Reset Parent Transform Position”

  • the parent will be positioned at the center of all pivots of the selected childs (at the same position of the selected child if it is only one) without affecting child positions

  • Rotation:

  • Select one child object in the hierarchy

  • right click it

  • select “Reset Parent Transform Rotation”

  • Parent will have the same rotation as the selected child without affecting child rotations

  • Scale:

  • Select one (parent) object in the hierarchy

  • right click it

  • select “Reset Local Scale”

  • The selected Object will get a localScale of (1,1,1) without affecting child scale

You can Undo these operations. Make sure to put the class in a Folder called “Editor” or you won’t be able to build the game!
Licence as always: do what you want with it, but don’t sue me (MIT Licence, I guess)

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class ContextMenuExtensions
{

    [MenuItem("GameObject/Reset Parent Transform Position", false, 10)]
    public static void ResetParentTransformPosition()
    {
        if (!Selection.activeGameObject) return;
        if (!Selection.activeGameObject.transform) return;
        if (!Selection.activeGameObject.transform.parent) return;

        Transform parentTransform = Selection.activeGameObject.transform.parent;
        Vector3 targetPosition = Vector3.zero;

        int count = 0;
        foreach (Transform t in Selection.transforms)
        {
            count++;
            targetPosition += t.position;
        }
        if (count > 1)
        {
            targetPosition /= count;
        }

        // keep all child positions and reposition the parent
        Undo.RecordObject(parentTransform, "Reset Parent Transform Position");

        List<Vector3> childPositions = new List<Vector3>();
        foreach (Transform child in parentTransform)
        {
            Undo.RecordObject(child, "Reset Parent Transform Position");
            childPositions.Add(child.position);
        }

        parentTransform.position = targetPosition;

        for (int i = 0; i < childPositions.Count; i++)
        {
            parentTransform.GetChild(i).position = childPositions[i];
        }
    }

    [MenuItem("GameObject/Reset Parent Transform Rotation", false, 10)]
    public static void ResetParentTransformRotation()
    {
        if (!Selection.activeGameObject) return;
        if (!Selection.activeGameObject.transform) return;
        if (!Selection.activeGameObject.transform.parent) return;

        Transform parentTransform = Selection.activeGameObject.transform.parent;

        // keep all child rotations and rerotate the parent
        Undo.RecordObject(parentTransform, "Reset Parent Transform Rotation");

        List<Quaternion> childRotations = new List<Quaternion>();
        List<Vector3> childPositions = new List<Vector3>();
        foreach (Transform child in parentTransform)
        {
            Undo.RecordObject(child, "Reset Parent Transform Rotation");
            childRotations.Add(child.rotation);
            childPositions.Add(child.position);
        }

        parentTransform.rotation = Selection.activeGameObject.transform.rotation;

        for (int i = 0; i < childRotations.Count; i++)
        {
            parentTransform.GetChild(i).rotation = childRotations[i];
            parentTransform.GetChild(i).position = childPositions[i];
        }
    }

    [MenuItem("GameObject/Reset Local Scale", false, 10)]
    public static void ResetLocalScale()
    {
        if (!Selection.activeGameObject) return;
        if (!Selection.activeGameObject.transform) return;

        Transform transform = Selection.activeGameObject.transform;

        // keep all child scales and rescale the parent
        Undo.RecordObject(transform, "Reset Local Scale");

        List<Vector3> childScales = new List<Vector3>();
        List<Vector3> childPositions = new List<Vector3>();
        foreach (Transform child in transform)
        {
            Undo.RecordObject(child, "Reset Local Scale");
            childScales.Add(child.localScale);
            childPositions.Add(child.position);
        }

        transform.localScale = Vector3.one;

        for (int i = 0; i < childScales.Count; i++)
        {
            transform.GetChild(i).localScale = childScales[i];
            transform.GetChild(i).position = childPositions[i];
        }
    }
}
1 Like

I know this is hell old post.

but this solution wont work if your object is moving along with rotation,

Just move the parent while it’s not parented?

What’s the point of parenting the object if you don’t want to move it along with it anyways.

With something like Character controller where it rotate while moving, you cant do what you say:))

This is the solution I found where the camera need to follow the player but not rotate with him

Keep in mind that the deltaPositionBetweenCameraAndPlayer is calculated at the start of the game where the different were set as desired

    private void LateUpdate()
    {
        var playerPosition = transform.position;
        var cameraPosition = gameplayCamera.transform.position;
        cameraPosition.x = playerPosition.x - deltaPositionBetweenCameraAndPlayer.x;
        cameraPosition.y = playerPosition.y - deltaPositionBetweenCameraAndPlayer.y;
        cameraPosition.z = playerPosition.z - deltaPositionBetweenCameraAndPlayer.z;
      
        gameplayCamera.transform.position = cameraPosition;
    }
child.transform.localRotation = Quaternion.Inverse(parentRotation);
5 Likes