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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Rotating a bone with script

Discussion in 'Scripting' started by rmele09, Mar 20, 2015.

  1. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    So I am trying to rotate an animated bone with LateUpdate. I read in a post somewhere that it is called after the animations, this way it overrides the animation rotation. Here is my current code, that does not appear to be doing anything:

    Code (JavaScript):
    1. var playerRibcage : Transform;
    2.  
    3. // LATE UPDATE
    4. var verticalSpeed : float = 20.0;
    5.  
    6. function LateUpdate ()
    7. {
    8. var v : float = verticalSpeed * Input.GetAxis ("Mouse Y");
    9.         playerRibcage.transform.Rotate (v, 0, 0);
    10. }
    11.  
     
    Last edited: Mar 20, 2015
  2. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
  3. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    515
    Try it with a simple LookAt rotation, and see if it works. If yes, then you know that the "counter-rotating" might be too slow or something. I never used smooth rotating of bones in LateUpdate, but I successfully set their rotations instantly via LookAt and setting their eulerAngles.
     
    rmele09 likes this.
  4. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    I have made some great progress but I need a little help! This code works, but for some reason it rotates the bone originally the wrong way, sideways and up as you can see in the picture. (Her arms are not facing forward) It rotates it vertically correctly afterwards, but why is it rotating the bone in the wrong direction at first? Here is a pic and the code:
    1.png
    Code (JavaScript):
    1. // LATE UPDATE
    2. var verticalSpeed : float = 5.0;
    3. var ribSpin : float = 0;
    4.  
    5. function LateUpdate ()
    6. {
    7.         ribSpin += Input.GetAxis ("Mouse Y") * verticalSpeed;
    8.         freyaRibcage.eulerAngles = new Vector3(0, 0, ribSpin);
    9.         freyaRibcage.rotation = transform.rotation * freyaRibcage.rotation;
    10. }
     
    Last edited: Mar 21, 2015
  5. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,924
    It looks like it's an issue with the rotation math sequence. The idea is, you apply a world rotation, then work your way down with local rotations. Each multiply on the end applies itself to what you have so far, as a local rotation.

    So that line 9, it starts with the player's world rotation. Then sets the ribcage's local rotation to (0,0,ribSpin). The problem, I'm guessing, is the ribcage has a non-zero resting rotation, which is getting thrown away. Accounting for would look like transform.rotation * ribRestRotation * bonusSpin.

    But, and it's been a while since I've done this, each animation step should be resetting the ribcage correctly, each frame, (unless you're using Additive animations,) so you can probably key off of that . This should "look like" a more obvious solution:

    Quaternion bonusSpin=Quaternion.Euler(0,0,ribSpin);
    ribCage.rotation = ribCage.rotation*bonusSpin;
     
  6. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Thank you so much for taking the time to explain that and give me that example, it seems to be working!! This subject is out of my scope of understanding so you really did me a huge favor here I really appreciate it. I am sure I will hit a snag when I start the networking code but I will cross that bridge when I get there. Thank you again you are the man.

    If it is not too much trouble, I would like to pick your brain about limiting the rotation angle of the bone. Basically, setting a "clamp vertical" that you see with the unity first person controller. Right now you can keep rotating the bone until the arms twist all the way around, I need to limit the rotation. Thanks again you are really doing me a favor here!
    -Raffaele
     
  7. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,924
    I wasn't sure it would work. Most people are using Mechanim now, and I've only used the old system. I thought Mechanim was just a layer on top of the old system (which works really well.) I guess it is.

    That ribSpin is just a number, so could be limited/clamped the same as any other number.

    Of course, it's local spin, so only limits the arm from where it is now. If you lean back, the arm can go back more. If you wanted to limit it to a WORLD angle (say it can rotate to straight up, but no more,) I think that involves a frame of reference switch: local to world, fix it, then back. That's a whole thing right there.
     
  8. Xatu1992

    Xatu1992

    Joined:
    Mar 22, 2015
    Posts:
    13
    Personally I would use the new Mechanim system for all movement etc itll slow performance scripting movements.
    The only way i can think of for the way you want without slow performance would be...

    make 3 var (game-objects) [Shoulder, Elbow, Hand]
    then just make them rotate using a function and call it into start or even when you click a button down.

    I haven't read above comments. Just my suggestion.
     
  9. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Almost 9 years later this helped me again LOL thank you.
     
  10. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I modify bone rotation a little different:
    Code (CSharp):
    1. [Header("Right Leg")]
    2.     [Range(0, 230)] // 165 straight
    3.     public float rightLegRotX;
    4.     [Range(-60, 80)]
    5.     public float rightLegRotY;
    6.     [Range(-90, 20)] // inverse of left
    7.     public float rightLegRotZ;
    8.     Quaternion rightLegRot;
    9.    
    10.     void RightLegRotations()
    11.     {
    12.         SetInstantRotation(rightLeg, rightLegRot, rightLegRotX, rightLegRotY, rightLegRotZ);
    13.         SetInstantRotation(rightShin, rightShinRot, rightShinRotX, rightShinRotY, rightShinRotZ);
    14.         SetInstantRotation(rightFoot, rightFootRot, rightFootRotX, rightFootRotY, rightFootRotZ);
    15.         SetInstantRotation(rightToe, rightToeRot, rightToeRotX, rightToeRotY, rightToeRotZ);
    16.  
    17.         rightLegRot = rightLeg.transform.localRotation;
    18.         rightShinRot = rightShin.transform.localRotation;
    19.         rightFootRot = rightFoot.transform.localRotation;
    20.         rightToeRot = rightToe.transform.localRotation;
    21.     }
    22.    
    23.     void SetInstantRotation(GameObject bone, Quaternion modRot, float X, float Y, float Z)
    24.     {
    25.         Quaternion check = Quaternion.Euler(X, Y, Z);
    26.  
    27.         if (modRot != check)
    28.         {
    29.             //print($"{bone} set rotation");
    30.             bone.transform.localRotation = check;
    31.         }
    32.     }
    There's way more to the script, especially for rotate bone by percentage, or by angle per frame, but the above should give all the "meat and potatoes" for any other new methods you so choose. :)
     
    rmele09 likes this.
  11. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Thank you so much for this. Basically what I am trying to achieve is for a first person game. I have a character you walk up to and interactive with, but I want to animate the characters neck bone to look at the player while you are in front of the character, and to the left a little bit and to the right a little bit, then once you are too far left or right from the character the bone rotates back to look naturally forward. So basically I need it animating follow the character and then at a certain angle or when you hit a trigger, animate back to maybe another target point that is placed in front of the character if that makes sense. The current code I have is not behaving correctly, because when I hit play the bone is turning sideways but then it follows the character at the wrong angle, do you think your code can work for what I am trying to achieve? Here is the script that is currently not working correctly:

    // Variables
    public Transform target; //the enemy's target
    Transform myTransform; //current transform data of this enemy
    public float rotationSpeed = 1.0f;
    // State Variables
    bool follow = true;
    private void Awake()
    {
    myTransform = transform; //cache transform data for easy access/performance
    }
    // Start is called before the first frame update
    void Start()
    {




    // Enemy follow target
    target = GameObject.FindWithTag("Echo_FollowTarget").transform; //target the player
    follow = true;
    }
    // Update is called once per frame
    void LateUpdate()
    {




    if (follow == true)
    {
    // ROTATE towards player
    myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
    Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed * Time.deltaTime);
    }
    }



    Screenshot (2100).png
     
  12. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Oh also, the character is already playing an Idle animation, so I need this to work on top of that animation playing. I have it executing in LateUpdate, which seems to be working well but for whatever reason the initial angle of the bone is starting out sideways and I don't know how to fix that. Any ideas on how I can adjust the code I have to get it to work or if your method can work?
     
  13. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Of course, basically the way I set it up was the full "allowed" rotation was set from 0-100%, so like in your case the head won't pull an exorcist move, lol!

    But normal rotation is figured by direction, which is (there - here = direction):
    Code (CSharp):
    1. Vector3 direction = (turnToPosition - transform.position).normalized; // sets length of 1
    2.     //direction.y = 0; // needed if not aiming up/down
    3.     Quaternion targetRotation = Quaternion.LookRotation(direction, Vector3.up); // get quat rotation from direction
    4.     transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, turnSpeed); // force rotation
    Another thing you might need, I just found, was finding a Vector3 along a line(point to point) by percentage of that length:
    Code (CSharp):
    1. Vector3 FindAlongLine(Vector3 start, Vector3 end, float percent)
    2.     {
    3.         return (start + percent * (end - start));
    4.     }
    You might not need that, but save it in your notes, as is a life saver when I figured it out, lol..

    Actually looking through my old code, it looks like I used distance(basically direction not normalized) from objA to objB, made a point from objA's forward with that distance, then used subtracted X,Y,Z coordinates to determine more or less percentage of full allowed rotation. Which looking at that, I want to redo it, lol..

    As it would just take a few test runs(using Debug.DrawRay) to calculate turn boneRotY +/- depending on (direction v. direction), or (targetRotation v. targetRotation)...

    I'm gonna need some time for that, if you don't figure it out first, as I'm on another project atm. :)
     
    Last edited: Sep 4, 2023
  14. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Not only Debug.DrawRay(Vector3 position, Vector3 direction),
    but also Debug.DrawLine(Vector3 position, Vector3 position)
    are life savers when playing with rotations, so you can physically see the lines(in scene mode, gizmos on).

    But the hardest part about all of it is figuring the difference between a Vector3 position versus a Vector3 direction, as they are different. But those debug calls will help any confusion.
     
  15. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Unfortunately this is still breaking her neck in the same way the other code was before starting the rotate. Could it be something weird with the rig or something? It is a mixamo rig, its playing animations correctly, but anytime I try to animate the neck bone the neck breaks!
     
  16. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    It's more than likely from the forward, use the debug rays I mentioned, https://docs.unity3d.com/ScriptReference/Debug.DrawRay.html, and do it from each bone(you modify) to understand and see which way they're oriented. Because what you might think is forward is probably left or some other direction. So when you say look here, it probably is, lol, so then in that case.. If you can't get into a modelling program to edit the bones, you have to make the script compensate.

    Here was a method I made, that calculated a flying plane to make it's right side it's technical forward, so it would fly in circles around a point:
    Code (CSharp):
    1. float sideDirection = Vector3.Dot((Vector3.Cross(transform.forward,
    2.             target.transform.position - transform.position)), Vector3.up);
    Which CROSS was how to reorient the forward direction, and DOT was the way to give a float of (1)forward, (0)sides, (-1)back. My logic on Cross, and Dot, are still a little shaky, so at best that's all I know, lol... Haven't fully studied them, I just make whatever I need to work for my situation at the time. But study into them if you can, as they are great for every day use(once you understand them). :)
     
  17. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    I’ve been trying a lot of combinations to get the direction correct but ive made very little progress. I have the neck initially upright but its still in the wrong direction and when it starts animating it goes down into its chest or if I play around with the bone direction it just keeps doing funny stuff
     

    Attached Files:

  18. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    I think that should work for an independent bone but here you need to take into account the rotation of the bone the neck is attached to, it should be the chest.
     
    rmele09 likes this.
  19. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    The animation should be set by local values, so if you change the bones rotation, it should snap to where that animation tells it to go. Unless in some way the animator only moves +rotation instead of =rotation, I always thought it was =rotation. As you could bend the bones any which way you wanted, but as soon as you say 'jump' or 'walk' it would go to what positions were set.

    Unless the rotation is so far off, it's trying to rotate the long way around, and is getting stopped by a min/max rotation value.. hmmmm...

    Or do you mean you made the animations yourself? If so, that would make sense, since you probably only use +rotation. But what I do, when I make my (script controlled)animations is get all the "normal" offsets which is basically a T-pose, and then only add to that with new offsets for animations from that pose. My ambition last led me to making other starter poses, like squatting(crouching) for example, then my ambition ran out, lol, and haven't touched it since.

    But you need to use Debug.DrawRay(or Line) to see what each rotation is doing. I normally have a blue line for bone forward, and red to where a new rotation is target, but that's just personal preference. But seeing what you have, and where you want to go(or where you declare to go), and seeing what the lines are doing makes way more sense than just watching the model(trust me).
     
    rmele09 likes this.
  20. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    I’m going to give the debugging lines a shot. However, can you explain or show your code for what you described in this part of your answer? That sounds exactly like what I am trying to achieve but I don’t understand how you are executing that. Any info would be awesome!
     
    Last edited: Sep 5, 2023
  21. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Ohh do you mean the +rotation/=rotation part?

    well plus rotation is more of if (Euler)rotation != (Euler)rotation: keep adding/subtracting till it is. And equals rotation is more of it equals this rotation rotation at start, then add/subtract a set value depending on distance and frames.

    +rotation can work great(looks smooth) if you set in enough conditionals(add or subtract depending on closer angle). But +rotation can also look bad without those checks, as it may only add(leading to a head rotating through the neck and body before snapping back into place).

    And =rotation can work or look fine as long as you are starting from set values(t-pose, standing, crouching, etc...), as stopping the animation can look jittery, since it snaps back into place(which is also good for reset).

    They both have their bonuses, and flaws, depending, so I have yet to find a sweet spot. As I mentioned, just starting from a T-pose being the main set was easy, but getting into other starter poses became a headache. But if you mean what the code looks like?
    snapping to position:
    Code (CSharp):
    1. void InstantStand()
    2.     {
    3.         bodyHeightNew = 0.01f;
    4.         bodyForwardNew = 0;
    5.         spineRot_X = 0;
    6.         spine1Rot_X = 0;
    7.         spine2Rot_X = 0;
    8.         spine3Rot_X = 0;
    9.  
    10.         ArmsRelaxed();
    11.  
    12.         RotateLegR(180, 0, 0); // standing
    13.         RotateLegL(180, 0, 0); // standing
    14.         RotateShinR(0, 0, 0); // straight
    15.         RotateShinL(0, 0, 0); // straight
    16.         RotateFootR(-50, 0, 0); // normal
    17.         RotateFootL(-50, 0, 0); // normal
    18.         RotateToeR(40, 180, 0); // straight
    19.         RotateToeL(40, 180, 0); // straight
    20.     }
    21. void HandOnKneeSquat()
    22.     {
    23.         RotateArmR(0, 95, -80); // slightly out from side
    24.         RotateArmL(0, -95, 80); // slightly out from side
    25.         RotateForearmR(20, 50, 50); // out forward, hand down
    26.         RotateForearmL(20, -50, -50); // out forward, hand down
    27.         RotateHandR(0, 0, 25); // slightly up
    28.         RotateHandL(0, 0, -25); // slightly up
    29.     }
    as this would be either a quick set, or basically if an animation was almost done, just to make the last frame kick to proper values. Setting those with:
    Code (CSharp):
    1. void RotateLegR(float X, float Y, float Z)
    2.     { rightLegRotX = X; rightLegRotY = Y; rightLegRotZ = Z; }
    3.     void RotateLegL(float X, float Y, float Z)
    4.     { leftLegRotX = X; leftLegRotY = Y; leftLegRotZ = Z; }
    5.     void RotateShinR(float X, float Y, float Z)
    6.     { rightShinRotX = X; rightShinRotY = Y; rightShinRotZ = Z; }
    7.     void RotateShinL(float X, float Y, float Z)
    8.     { leftShinRotX = X; leftShinRotY = Y; leftShinRotZ = Z; }
    9.     void RotateFootR(float X, float Y, float Z)
    10.     { rightFootRotX = X; rightFootRotY = Y; rightFootRotZ = Z; }
    11.     void RotateFootL(float X, float Y, float Z)
    12.     { leftFootRotX = X; leftFootRotY = Y; leftFootRotZ = Z; }
    13.     void RotateToeR(float X, float Y, float Z)
    14.     { rightToeRotX = X; rightToeRotY = Y; rightToeRotZ = Z; }
    15.     void RotateToeL(float X, float Y, float Z)
    16.     { leftToeRotX = X; leftToeRotY = Y; leftToeRotZ = Z; }
    which of course those were set by the constants:
    Code (CSharp):
    1. void RightLegRotations()
    2.     {
    3.         SetInstantRotation(rightLeg, rightLegRot, rightLegRotX, rightLegRotY, rightLegRotZ);
    4.         SetInstantRotation(rightShin, rightShinRot, rightShinRotX, rightShinRotY, rightShinRotZ);
    5.         SetInstantRotation(rightFoot, rightFootRot, rightFootRotX, rightFootRotY, rightFootRotZ);
    6.         SetInstantRotation(rightToe, rightToeRot, rightToeRotX, rightToeRotY, rightToeRotZ);
    7.  
    8.         rightLegRot = rightLeg.transform.localRotation;
    9.         rightShinRot = rightShin.transform.localRotation;
    10.         rightFootRot = rightFoot.transform.localRotation;
    11.         rightToeRot = rightToe.transform.localRotation;
    12.     }
    13. // reading the main:
    14. void SetInstantRotation(GameObject bone, Quaternion modRot, float X, float Y, float Z)
    15.     {
    16.         Quaternion check = Quaternion.Euler(X, Y, Z);
    17.  
    18.         if (modRot != check)
    19.         {
    20.             //print($"{bone} set rotation");
    21.             bone.transform.localRotation = check;
    22.         }
    23.     }
    Which technically one could assume to just give positional data each frame, which was something I was working on:
    Code (CSharp):
    1. rightLegRotX = MovingFloatValue(rightLegRotX, newLegR.x, distLegR.x / inFrames);
    2.         rightLegRotY = MovingFloatValue(rightLegRotY, newLegR.y, distLegR.y / inFrames);
    3.         rightLegRotZ = MovingFloatValue(rightLegRotZ, newLegR.z, distLegR.z / inFrames);
    4.         rightShinRotX = MovingFloatValue(rightShinRotX, newShinR.x, distShinR.x / inFrames);
    5.         rightShinRotY = MovingFloatValue(rightShinRotY, newShinR.y, distShinR.y / inFrames);
    6.         rightShinRotZ = MovingFloatValue(rightShinRotZ, newShinR.z, distShinR.z / inFrames);
    7.         rightFootRotX = MovingFloatValue(rightFootRotX, newFootR.x, distFootR.x / inFrames);
    8.         rightFootRotY = MovingFloatValue(rightFootRotY, newFootR.y, distFootR.y / inFrames);
    9.         rightFootRotZ = MovingFloatValue(rightFootRotZ, newFootR.z, distFootR.z / inFrames);
    10.         rightToeRotX = MovingFloatValue(rightToeRotX, newToeR.x, distToeR.x / inFrames);
    11.         rightToeRotY = MovingFloatValue(rightToeRotY, newToeR.y, distToeR.y / inFrames);
    12.         rightToeRotZ = MovingFloatValue(rightToeRotZ, newToeR.z, distToeR.z / inFrames);
    13. // needing:
    14. newLegR = (Vector3)data.GetField("LegR").GetValue(data);
    15.         distLegR = VectorAbsoluteDistance(newLegR, rightLegRotX, rightLegRotY, rightLegRotZ);
    16.         newShinR = (Vector3)data.GetField("ShinR").GetValue(data);
    17.         distShinR = VectorAbsoluteDistance(newShinR, rightShinRotX, rightShinRotY, rightShinRotZ);
    18.         newFootR = (Vector3)data.GetField("FootR").GetValue(data);
    19.         distFootR = VectorAbsoluteDistance(newFootR, rightFootRotX, rightFootRotY, rightFootRotZ);
    20.         newToeR = (Vector3)data.GetField("ToeR").GetValue(data);
    21.         distToeR = VectorAbsoluteDistance(newToeR, rightToeRotX, rightToeRotY, rightToeRotZ);
    22. // and needing:
    23. Vector3 VectorAbsoluteDistance(Vector3 newPos, float X, float Y, float Z)
    24.     {
    25.         return new Vector3(
    26.             Mathf.Abs(newPos.x - X),
    27.             Mathf.Abs(newPos.y - Y),
    28.             Mathf.Abs(newPos.z - Z));
    29.     }
    30. // and needing:
    31. float MovingFloatValue(float actual, float goal, float speed)
    32.     {
    33.         if (actual < goal - speed)
    34.         {
    35.             return actual + speed;
    36.         }
    37.         else if (actual > goal + speed)
    38.         {
    39.             return actual - speed;
    40.         }
    41.         else { return goal; }
    42.     }
    Then I eventually found that certain bone rotations wouldn't line up, like the difference between upper arm and fore arm, or say thigh moving with shin, so cutting those values into a 4 part check worked:
    Code (CSharp):
    1. float RotationOfFourStages(float percentage, float stage1, float stage2, float stage3, float stage4)
    2.     {
    3.         if (percentage < 25)
    4.         {
    5.             float fraction = stage1 / 25;
    6.             return fraction * percentage;
    7.         }
    8.         else if (percentage < 50)
    9.         {
    10.             float fraction = stage2 / 25;
    11.             return fraction * (percentage - 25) + stage1;
    12.         }
    13.         else if (percentage < 75)
    14.         {
    15.             float fraction = stage3 / 25;
    16.             return fraction * (percentage - 50) + stage1 + stage2;
    17.         }
    18.         else
    19.         {
    20.             float fraction = stage4 / 25;
    21.             return fraction * (percentage - 75) + stage1 + stage2 + stage3;
    22.         }
    23.     }
    Which I mainly think was needed for the crouching animation, as thigh and shin would move fast in one quarter, but slower in another, here's that method:
    Code (CSharp):
    1. void Crouching()
    2.     {
    3.         float setHeight = 0; //-0.005f;
    4.         //float crouchVariable = (mayaSize - 0.3f) * 50; // * 100; is .3 to.4 @100%
    5.        
    6.         float fullTravel = 0.036f; // was 0.031f
    7.         float stage1 = fullTravel * 0.048f;
    8.         float stage2 = fullTravel * 0.2f;
    9.         float stage3 = fullTravel * 0.322f;
    10.         float stage4 = fullTravel * 0.42f; // equals 0.99 ?? so 1 equals normal, and zero is nothing
    11.         setHeight -= RotationOfFourStages(crouchPercent, stage1, stage2, stage3, stage4);
    12.  
    13.         //rightLegRotY = 20;
    14.         //leftLegRotY = -20;
    15.         //rightShinRotZ = -5; // or 6?
    16.         //leftShinRotZ = 5; // or 6? <-- was cowgirl other leg rots?
    17.  
    18.         // RotationVariable = (Rotation@0%) - (1%moveValue) * PositionPercent;
    19.  
    20.         rightLegRotX = 90f - 0.78f * crouchPercent;
    21.         leftLegRotX = 90f - 0.78f * crouchPercent;
    22.         rightShinRotX = 0 + 1.7f * crouchPercent; // was 1.55
    23.         leftShinRotX = 0 + 1.7f * crouchPercent; // was 1.55
    24.         rightFootRotX = 0 - 0.4f * crouchPercent;
    25.         leftFootRotX = 0 - 0.4f * crouchPercent;
    26.  
    27.         if (bodyHeightNew != setHeight) { bodyHeightNew = setHeight; }
    28.     }
    But as you can see, you need plenty of checks, and to do some decent mathematics to basically make keyframes(just normal frames) in order for it to work properly.

    Now one could argue, why not just use the Animator, and set keyframes within a standard animation? Well my answer was simply, this was a build for AI, and each rotation of each bone was to be handled by a brain, and the model would be as close to real life(inside the game) as much as possible. With even the feet using load bearing points, to actually move realistically.

    Which is a nightmare to do as a one man team.. lol.. But still didn't stop me from trying!
     
    rmele09 likes this.
  22. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Ohhh and as far as plus rotation, I was working on a method for that as well:
    Code (CSharp):
    1. void ArmR_MoveAtSpeed(float X, float Y, float Z, float speed)
    2.     {
    3.         if (rightArmRotX < X - speed) { rightArmRotX += speed; }
    4.         else if (rightArmRotX > X + speed) { rightArmRotX -= speed; }
    5.         if (rightArmRotY < Y) { rightArmRotY += speed; }
    6.         else if (rightArmRotY > Y) { rightArmRotY -= speed; }
    7.         if (rightArmRotZ < Z) { rightArmRotZ += speed; }
    8.         else if (rightArmRotZ > Z) { rightArmRotZ -= speed; }
    9.     }
    10.     void ForearmR_MoveAtSpeed(float X, float Y, float Z, float speed)
    11.     {
    12.         if (rightForearmRotX < X - speed) { rightForearmRotX += speed; }
    13.         else if (rightForearmRotX > X + speed) { rightForearmRotX -= speed; }
    14.         if (rightForearmRotY < Y) { rightForearmRotY += speed; }
    15.         else if (rightForearmRotY > Y) { rightForearmRotY -= speed; }
    16.         if (rightForearmRotZ < Z) { rightForearmRotZ += speed; }
    17.         else if (rightForearmRotZ > Z) { rightForearmRotZ -= speed; }
    18.     }
    By incorporating speed values, which were calculated by frames needed overall, and distances of each frame rotation.
     
    rmele09 likes this.
  23. rmele09

    rmele09

    Joined:
    Nov 8, 2010
    Posts:
    697
    Thank you for the detailed post. I have a lot to unpack here LOL I will post back once I get a chance to try this out! Thank you very much.