How to avoid changing transform.parent?

Given the following game object hierarchy in Unity 3D:

"Super Parent"    scale (2, 34, 5), rotation(45, 16, 20)
     |
     ----> "Parent of Container"   fixed-scale (1, 1, 1), fixed-rotation(0, 0, 0)
             |
             ----> "Container"   scale (1, 2, 3), fixed-rotation(0, -180, 0)
                     |
                     ----> "Nested"   scale (4, 5, 6), rotation(14, 54, 71)

In the following snippet I am achieving ths following:

  • Change local scale of “Container” without affecting the size of “Nested” in world space.
  • Change the scale of “Nested” using the local space of “Parent of Container”.

As many will know the local scale of a parent game object will alter the visual scale of nested objects so that when they are measured using world space appear different. To counteract this the local scale of “Nested” must also be updated to compensate for the change so that its size in the world remains unchanged whilst the scale of the container is increased.

I have implemented this (and it is working) with the following solution:

// Temporarily re-parent to "Parent of Container"
nestedTransform.parent = container.parent;

// I can now adjust the size of the container without affecting the
// size of the "Nested" when measured in world space.
containerTransform.localScale = newContainerScale;

// Assign new scale to "Nested" using local space of "Parent of Container"
nestedTransform.localScale = newScale;

// Re-parent "Nested" into "Container"
nestedTransform.parent = containerTransform;

// In the case where `nestedTransform.localScale` is not actually changed,
// after re-parenting it will be changed to (2, 2.5, 3) meaning that its
// size in world space is unchanged whilst "Container" is larger.

Whilst this is achieving exactly what I need, the process of re-parenting game objects does all sorts of other processor intensive stuff that is not wanted.

How can the above be achieved using just matrices and vectors? For each transform there is a local-to-world and world-to-local matrix which might be useful here.

Problem solved by performing all calculations using matrices instead and then decomposing into the separate position, rotation and scale values. These separate values can then be assigned to the transform component which correctly scales object without distorting it.

References:

This took me a little while to figure out, though here is some information which future readers may find useful:

Why do you do this parenting stuff at all? assigning localScale will never change scale of parent.


If we’re talking about uniform scales you can do this:

Vector3 oldPosition = nested.position;
controller.localScale = Vector3.one * newScale;
nested.position = oldPosition;
nested.localScale = Vector3.one * (1 / newScale);