Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Problem in parent's asymmetric scaling

Discussion in 'Scripting' started by Hecocos, Oct 8, 2023.

  1. Hecocos

    Hecocos

    Joined:
    Nov 29, 2021
    Posts:
    15
    Hi, Here is my usage scenario:
    upload_2023-10-8_16-34-54.png
    I have two cubes with simple hierarchy, left one is parent, right one is child. Then I set parent's local scale with (2, 1, 1), the child cube will be affacted by parent's scaling by default. I want child cube to be the same size so I set it's localscale by (1/2, 1, 1). It's ok when these two cubes axis-aligned totally. But if i give a rotation to child cube, it will be distorting like this:
    upload_2023-10-8_16-45-39.png
    so, what i can do to fix this?
     
    Last edited: Oct 8, 2023
  2. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    541
    Make them both a child of an empty parent holder object and then you can transform both children individually or collectively.
     
    Bunny83 likes this.
  3. Hecocos

    Hecocos

    Joined:
    Nov 29, 2021
    Posts:
    15
    i can't change this hierarchy. cuz in my project, this scenario will become an avatar's skeleton, modify bone's scale to get different 'size' avatar. so i can't change model's hierarchy.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,711
    Then you will need to reinvent linear algebra.

    The artifact you see above is how non-uniform scaling is propagated down a stack of transforms.

    The solution is to ONLY scale leaf nodes.
     
    Last edited: Oct 9, 2023
    Bunny83 likes this.
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    Or scale the parent uniformly when needed. But yes, if you need non-uniform scaling, keep things separated.

    Bones should never change scale anyways. Bones rotates and in some rare cases might displace. However a skinned character (SkinnedMeshRenderer) would not grow or shrink at all when you scale the bone structure. If your character is made up of individual parts with separate renderers, What zulo said is the only viable solution then. Can you be a bit more specific of your actual usecase? In general you should never add child renderers to objects which also have a renderer on it. Exactly because of scaling issues.

    A Transform represents its own coordinate space. When you scale it non-uniformly, the whole space gets distorted with everything that lives in it. So when you have a longer chain of nested coordinate spaces and you introduce non-uniform scaling at several levels, you can end up with a heavily distorted space that's probably even hard to conceptualize in your mind. So what's your actual goal? You want to scale the parent but not scale the children? What do the different objects actually represent? When you have a skeletal animated character and you scale the whole thing on one axis, even the skinned animations would be distorted. So if an arm looks thin and long when it's hanging down, it would look short and thick when it is stretched out since that's what the coordinate space itself looks like. You know, like those distorting mirrors. When you move the distortion will affect different parts of your image.
     
    Kurt-Dekker likes this.
  6. Hecocos

    Hecocos

    Joined:
    Nov 29, 2021
    Posts:
    15
    ok, I do it more specifically.
    I want to dev an UGC game that players can modify them character's size of different part. Let's say i wanna change width of character's upperarm, but i don't want to change lowerarm's width either. Like i set upperarm's scale to (2, 1, 1), but it effect lowerarm and all children of it, that's not i want.
    I've try a lot of calculations on lowerarm's scale to make it stay (1, 1, 1) in WorldSpace, but failed.
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,843
    That still isn't done with scaling. It's done with bones that certain parts of the mesh are weighted to, and manipulated via scripts or animations. Or its done with blend shapes that you set in your meshes before exporting, and modify via scripting.
     
    Kurt-Dekker and lordofduct like this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,711
    Start with two bones and skinned animation and get it working 100%.

    Do not even consider moving onto a more-complex model than 2 bones until you understand every single part of every piece of data that goes in to the modification transformation you want to have.

    Any further work beyond two bones and proving your idea out is just clutter blocking your way.
     
  9. Hecocos

    Hecocos

    Joined:
    Nov 29, 2021
    Posts:
    15
    Wow!Your idea on blend shapes inspried me!Maybe i can focus on bindPoses of SkinnedMesh?Scaling on target bone's bindPose can also affect Vertexs that weighted to this bone!I will try it rightnow.
     
  10. Hecocos

    Hecocos

    Joined:
    Nov 29, 2021
    Posts:
    15
    In two bones situation, I can't get it working 100% when using non-uniform scale like (2, 1, 1) on parent. This is my calculation below, let's say targetBone has only one child:
    Code (CSharp):
    1. targetBone.localScale = targetScale;
    2.  
    3.         for (int i = 0; i < targetBone.childCount; i++)
    4.         {
    5.             var childBone = targetBone.GetChild(i);
    6.             var childDesiredWorldMatrix = Matrix4x4.identity;
    7.             childDesiredWorldMatrix.SetTRS(childBone.position, childBone.rotation, Vector3.one);
    8.             var diffMatrix = targetBone.transform.worldToLocalMatrix * childDesiredWorldMatrix;
    9.             childBone.localScale = diffMatrix.lossyScale;
    10.             Debug.Log($"ChildBone's scale: {childBone.localToWorldMatrix.lossyScale}");
    11.         }
    Which i desired the result of childBone's scale is equal to (1, 1, 1). But it's not when the childBone rotating around Y-axis.
    upload_2023-10-11_10-57-46.gif
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,711
    Correct. Hence what Spiney wrote above.

    Consider the transform on the final object itself to be a special bone that is centered at local (0,0,0) and whatever you do propagates through its matrix. That's why we leave it zero local position, identity scaling and identity rotation.

    Fire up Probuilder or Blender, make yourself a 2x1x1 cube and get on with your gamedev.

    I'm being serious. You're not going to change math.

    EDIT: Obviously you must APPLY all local transforms before saving the mesh in Blender. Obviously... otherwise you're right back where you are here.
     
    spiney199 likes this.