Search Unity

Question Move characters body according to amount of head rotation away from the body

Discussion in 'Scripting' started by SizeableNayNay, May 6, 2021.

  1. SizeableNayNay

    SizeableNayNay

    Joined:
    Apr 12, 2021
    Posts:
    3
    Hello men and women of the game making world, I'm currently making a small game with a character that can freely look around the world while the head rotates.

    Variables
    Code (CSharp):
    1. Quaternion bodyRotation;
    2. Quaternion oldBodyRotation;
    3.  
    4. Vector3 totalRotation;
    5.  
    6. float xRotation = 0f;
    7. float yRotation = 0f;
    Code for the method to rotate camera
    Code (CSharp):
    1.     void RotateView()
    2.     {
    3.         float remainder; // body rotation - head rotation
    4.  
    5.         bodyRotation = gameObject.transform.rotation;
    6.  
    7.         // Mouse inputs
    8.         totalRotation.x -= Input.GetAxis("Mouse Y");
    9.         totalRotation.y += Input.GetAxis("Mouse X");
    10.  
    11.         // Clamp vertical quaternion
    12.         totalRotation.x = Mathf.Clamp(totalRotation.x, -70f, 70f);
    13.  
    14.         mainCamera.transform.rotation = Quaternion.Euler(totalRotation.x, totalRotation.y, 0f);
    15.         playerhead.transform.rotation = Quaternion.Euler(totalRotation.x, totalRotation.y, 0f);
    16.  
    17.         remainder = bodyRotation.y - totalRotation.y;
    18.  
    19.         // If head is x amount away from body rotate body
    20.         if (remainder > bodyRotation.y + 60 || remainder < bodyRotation.y - 60)
    21.         {
    22.             // If head is too far right rotate body right with head
    23.             if (totalRotation.y >= bodyRotation.y - 60)
    24.             {
    25.                 bodyRotation.y -= remainder + 60;
    26.             }
    27.             else if (totalRotation.y <= bodyRotation.y + 60)
    28.             {
    29.                 bodyRotation.y -= remainder - 60;
    30.             }
    31.  
    32.             // Rotate body with given y rotation
    33.             gameObject.transform.rotation = Quaternion.Euler(0f, bodyRotation.y, 0f);
    34.         }
    35.  
    36.         oldBodyRotation = bodyRotation;
    37.     }
    Info
    The end goal of the characters look script is to allow the character to look 60 degrees to the left or right of the character and if the number is exceeded then the body should rotate with the characters head. I have this all working well apart from when the characters head is over 60 degrees the body will constantly rotate even when turning the other direction.

    The problem
    The problem I'm having in other words is that once the head has reached 60 degrees the body will rotate with the head, however as I'm decreasing the head angle the body still rotates although the body should be still until I surpass 60 degrees away. From looking at the inspector once the head is passed 60 degrees it will stay 60 degrees until the body returns to 0,0 again as the body is trying to return to 0,0 while the head is limiting it. As it took me 2 days to figure out how to get where I am now I'm stumped on this problem. :):rolleyes:

    Video


    Any input is much apricated!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    You cannot use the .y field of a Quaternion. Same goes for the .x, .z and .w fields. Those are NOT euler angles. They are internal vector quantities that are completely useless to you.

    You might be able to use the .eulerAngles.y property, but it is subject to gimbal lock and even before gimbal lock, it will always return between -180 and 180.

    It's always best to track your OWN float variable for heading and head-pointing, then drive the rotations directly. Here is such a discussion related to gun turrets:

    Turret aiming/rotating:

    https://forum.unity.com/threads/vector-lookat-unprecise.858511/#post-5658304
     
    SizeableNayNay likes this.
  3. SizeableNayNay

    SizeableNayNay

    Joined:
    Apr 12, 2021
    Posts:
    3
    Thanks for the quick reply, I'll have a look at the thread now. Although this might as well have been written in Spanish haha.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Okay, here it is another way:

    If you think the 60 here correlates to degrees, that's not correct. You are effectively comparing bananas and apples. How many bananas and apples are there in 60 degrees?

    Don't use those fields. They are not helpful to you.

    The key point is you should ONLY create and put Quaternions into a rotation (or localRotation).

    You should NEVER read Quaternions out of them unless you really know what you're doing.

    Instead, keep your own variables representing angles, and create Quaternions and put them INTO the rotation (or .localRotation).

    Create Quaternions using
    Quaternion.Euler(xAngle, yAngle, zAngle);
     
    Last edited: May 6, 2021
    SizeableNayNay likes this.
  5. SizeableNayNay

    SizeableNayNay

    Joined:
    Apr 12, 2021
    Posts:
    3
    This clears things up loads, I've read into eulerAngles and quaternions and It's helped to get a bigger understanding on how objects work in 3D. I would've totally over looked this doing my own research.
     
    Kurt-Dekker likes this.