Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by bartozwe · Aug 19, 2016 at 02:26 PM · transformscaleparentinglocalscalematrix4x4

How is localScale adjusted when re-parenting transforms?

I am trying to mimic Unity's behaviour where it concerns transform parenting, and I'm stumbling on something I can't explain.

Say I have 2 GameObjects. They both are without a parent. One is named "Root", the other "Child", because that is what the hierarchy will end up like. Both are already translated, rotated and Root is non-uniformly scaled.

Root

Child

Now, at run-time, I parent Child to Root. When this happens, Unity will preserve the global position and orientation of the Child, and in the documentation it also states it preserves scale. It does so by modifying the local transform values/matrix in such a way that its global transform is preserved. Or, that is the assumption.

What this new "local" matrix would need to be is

 localTransformMatrix = parentTransform.worldToLocalMatrix * childTransform.localToWorldMatrix;

localRotation and localPosition would be easy enough to derive. And the localScale would seem to be found in the length of the colums of the localTransformMatrix (or its 3x3 rotation part).

But ... that doesn't stroke with what Unity actually does. The new localScale I actually get is (0.6140807, 0.8078736, 0.4113787)

And that's where my confusion starts. If you parent objects, and inspect the localToWorldMatrix of the Child object, you'll notice that in fact it is modified. Global position and orientation are preserved, but there is an effect on the scale (and subsequently the localScale) that I can't seem to match when computing by hand.

So what is going on here? What is Unity actually doing when parenting, and how can I compute the correct values (matching what Unity gives) if I were to compute it by hand?

child.png (12.0 kB)
root.png (12.5 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by bartozwe · Aug 22, 2016 at 01:36 PM

The answer of @Bunny83 set me on the right track. The problem is indeed that any non-uniform scale will leave you with axes that are no longer perpendicular. So you need to correct for this.

If you do so by hand, you can still get a valid rotation matrix with perpendicular axes from the quaternion rotations.

 localRotation = (Quaternion.Inverse(parent.rotation) * rotation).normalized;

If you project the axes you get from

 localTransformMatrix = parentTransform.worldToLocalMatrix * childTransform.localToWorldMatrix;

onto the axes you get from the quaternion (by making it a matrix, let's say localRotationMatrix), you get the appropriate localScale values.

 float x = Vector3.Dot(new Vector3(localRotationMatrix.m00, localRotationMatrix.m10, localRotationMatrix.m20), new Vector3(localTransformMatrix.m00, localTransformMatrix.m10, localTransformMatrix.m20));
 //And similar for the y and z vectors. 

Plug those back into your local matrix transform, and when you update your localToWorldMatrix you'll see it will have the same values as Unity gives you.

Mystery solved.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by Bunny83 · Aug 20, 2016 at 02:02 AM

Well, the problem is that "scale" is always local to the local coordinate system along each local axis. As you might have discovered already, there is nothing like a world-space "scale" property like there is for position / rotation. Unity just provides the lossyScale property which tries to return "something" that comes closest to a worldspace scale. The scale is correctly displayed / calculated as long as all objects are only scaled uniformly (the same on all axis).

If you non-uniformly scale the parent and rotate the child, the child's local space will be deformed. That means the 3 local axis of the child are no longer be perpendicular to each other since the object will be skewed. In such cases it's impossible to calculate a worldspace scale for the child. Since parenting / unparenting a child should "perserve" it's worldspace properties, that's not possible for the scale.

In order to get the same worldspace properties, Unity has to adjust the local position / rotation / scale of the child object.

Keep in mind that an object actually only has it's local properties (localPosition, localRotation, localScale). The worldspace properties (position, rotation, lossyScale) are always calculated by taking the parent space(s) into account.

I'm not sure how Unity actually approximates the lossyScale since i never have thought about it ^^.

The basic rules you should keep in mind is:

  • If the parent is non-uniformly scaled, never rotate a child object. The only rotations that would kind of work are 90° steps from the identity rotation. That way the child axis are still aligned with the parent axis.

  • If the child should be rotated your parent(s) should only be scaled uniformly.

See this image as reference:

As you can see the axis of a rotated child are no longer perpendicular when you scale the parent non-uniformly. So you can't determine a world space scale based on that setup. Keep in mind that a worldspace scale would use the world axis. When scaled uniformly all proportions are preserved.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Aug 20, 2016 at 02:08 AM 0
Share

I "guess" that the lossy scale is calculated by projecting the local scale vector onto the corresponding world axis to get each component. Though i currently don't have time to conduct some tests on that matter.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to make an object's localscale values grow and shrink within a few seconds? 0 Answers

Rescaling goes wrong? 0 Answers

Attempting to Calculate and Change Scale of Platforms Sets Scale to 0 1 Answer

LocalScale and uv 1 Answer

Warning: "Setting scale failed, ignoring request." ? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges