Search Unity

Question Worng SignedAngle

Discussion in 'Scripting' started by Salja, Dec 7, 2020.

  1. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    Hello everyone, I have a little problem and unfortunately I can't go on on my own.
    I'm currently working on a character controller and I want to calculate the angle while walking (-180, -90, 0, 90, 180)
    The whole thing works even if I run normally and am not in strafe mode, but as soon as I go into the strafe mode I get strange values (-0.3694153, -2.219208 -21.25256) Unfortunately, I don't get the values like without a strafe.

    Because my English is not that good, I made another video


    Here the code

    Code (CSharp):
    1.         private void Update() {
    2.             inputX = Input.GetAxisRaw("Horizontal");
    3.             inputZ = Input.GetAxisRaw("Vertical");
    4.  
    5.             direction = new Vector3(inputX, 0, inputZ);
    6.             direction.Normalize();
    7.  
    8.             // Check if we have movement input
    9.             isMoving = direction != Vector3.zero;
    10.  
    11.             // If the movement is disabled return Vector.zero
    12.             direction = playerInput.isMovementEnabled ? direction : Vector3.zero;
    13.  
    14.             inputMagnitude = direction.magnitude;
    15.             inputMagnitude *= speedFactor;
    16.  
    17.             // Change MoveType if Player is in Stance to Strafe
    18.             moveMode = stance == Stances.OneHandSword ? MoveMode.Strafe : MoveMode.Directional;
    19.  
    20.             if (playerInput.isRotationEnabled && isMoving) {
    21.  
    22.                 // Normal Movement none Strafe
    23.                 if (moveMode == MoveMode.Directional) {
    24.                     targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
    25.                     angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothDamp);
    26.  
    27.                     transform.rotation = Quaternion.Euler(0f, angle, 0f);
    28.                 }
    29.  
    30.                 // Strafe Movement
    31.                 if (moveMode == MoveMode.Strafe) {
    32.                     targetAngle = cameraTransform.eulerAngles.y;
    33.                     angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothDamp);
    34.  
    35.                     transform.rotation = Quaternion.Euler(0f, angle, 0f);
    36.                 }
    37.             }
    38.  
    39.             Vector3 forwardA = cameraTransform.rotation * Vector3.forward;
    40.             Vector3 forwardB = transform.rotation * Vector3.forward;
    41.  
    42.             // get a numeric angle for each vector, on the X-Z plane (relative to world forward)
    43.             float angleA = Mathf.Atan2(forwardA.x, forwardA.z) * Mathf.Rad2Deg;
    44.             float angleB = Mathf.Atan2(forwardB.x, forwardB.z) * Mathf.Rad2Deg;
    45.  
    46.             // get the signed difference in these angles
    47.             float _signedAngle = Mathf.DeltaAngle(angleA, angleB);
    48.  
    49.             Debug.Log(_signedAngle);
    50.  
    51.             // Update Animator
    52.             animator.SetFloat(HashHorizontal, direction.x, speedSmoothDamp, Time.deltaTime);
    53.             animator.SetFloat(HashVertical, direction.z, speedSmoothDamp, Time.deltaTime);
    54.             animator.SetFloat(HashInputMagnitude, inputMagnitude, speedSmoothDamp, Time.deltaTime);
    55.             animator.SetInteger(HashStance, (int)stance);
    56.             animator.SetBool(HashIsGrounded, isGrounded);
    57.             animator.SetFloat(HashFalltime, lastFalltime);
    58.             animator.SetBool(HashIsCrouching, isCrouching);
    59.             animator.SetBool(HashIsDead, isDead);
    60.  
    61.             playerInput.UpdateInput();
    62.  
    63.             // Load ScriptableAbility on Update
    64.             for (int i = 0; i < abilities.Count; i++) {
    65.                 if (abilities[i].IsEnabled) {
    66.                     abilities[i].OnCharacterUpdate();
    67.                 }
    68.             }
    69.         }
    Screenshot_4.png
     
  2. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    "I don't get the values like without a strafe."

    What kind of angles are you looking for?
    Angles relative to what?
    And ...what actually isn't working because of this?

    I guess you are trying to calculate something relative to camera forward vs player movement... but it is not quite clear...

    In your normal movement you are using input direction vector to get angle:
    Code (CSharp):
    1. targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
    But in your strafe you are doing:
    Code (CSharp):
    1. targetAngle = cameraTransform.eulerAngles.y;
    So you are getting camera rotation relative to world axis. So if your camera is facing roughly forward in the world, you'll get values near 360 or 0. If your camera is facing the opposite direction, you'll get 180.
     
    Last edited: Dec 7, 2020
    Salja and Bunny83 like this.
  3. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    Thank you for your answer, i want to add a Dodge if the Player is in Strafe so thats why i want to calculate the angle. Example: if the player move to left in strafe with "KeyCode.S" and he press Space i want my character to dodge to the left side, so i think its character realtive to input ? i have no idea to calculate this.

    If i using the same code what i use for normal movement to rotate my character then the strafe rotation is not more working

    this are the values in my animator
    Screenshot_5.png
     
  4. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Sorry - still having hard time to figure out what you need.

    "if the player move to left in strafe with "KeyCode.S" and he press Space i want my character to dodge to the left side,"

    S key sounds a bit unusual for left movement in this kind 3rd person movement IMO. Maybe I'm not understanding something, but I'd expect A + some modifier key for strife left, and then space to dodge (or something).

    And I guess your WASD controls are camera relative? W is moving along camera forward, A is moving left camera relative and so on?

    And can you actually strafe while facing any direction? Like when moving towards camera? Based on your video, it seems like you can strafe L/R and F/B only when facing forwards relative to camera.
     
    Last edited: Dec 7, 2020
  5. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    I'm sorry for the bad explaining, yes i mean A not S Sorry.

    Here a Video, my Strafe works fine. Now i want if i press Space to Dodge in the Direction of the Input, for that i create a Blendtree.

    Screenshot_5.png

    At my Blendtree i have the Values -180, -90, 0, 90, 180 but now i need to calculate the angle to set the values before i press Space to Dodge in the right direction of the input.

    Move in the video to 0:22 this is the time i start strafing you can see the strafe works fine.
    You can see that too when I am not in Strafe i have a different movement style (no strafe) thats why i have 2 different rotations one for none strafe and one for strafe.

    Screenshot_6.png

    i dont know if this is needed or not ??? But Strafe works.

     
    Last edited: Dec 7, 2020
  6. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    OK. See this and try if it will give you what you want (I did some experimenting with some scene, not sure if this fits right into your code / this one only calculates angle, doesn't apply it to anything):
    Code (CSharp):
    1. if (moveMode == MoveMode.Strafe)
    2. {
    3.     var playerMoveDir = transform.InverseTransformDirection(direction);
    4.     targetAngle = Vector3.SignedAngle(Vector3.forward, playerMoveDir, Vector3.up);
    5. }
    This is what I've used once or twice and I guess this would also work, no matter if player is facing forward relative to camera or not.

    It works like this - If player faces forward relative to camera, and you press A, you'll get -90. If you press D you'll get 90. If your character faces right relative to camera, and you press W, you'll still get -90 and so on...

    I'm still not quite sure about movement possibilities and camera movement you are aiming for, but this is based on what I saw in the first video.
     
    Salja likes this.
  7. Salja

    Salja

    Joined:
    Mar 23, 2017
    Posts:
    353
    Really Thanks you give me the right way, i get it to work with

    Code (CSharp):
    1.                     Vector2 dir = new Vector2(transform.InverseTransformDirection(characterController.velocity).normalized.x, transform.InverseTransformDirection(characterController.velocity).normalized.z);
    2.                     var sideDir = dir.x;
    3.                     var forwardDir = dir.y;
    4.  
    5.                     if (Mathf.Abs(sideDir) > Mathf.Abs(forwardDir))
    6.                         dodgeAngle = sideDir * 90;
    7.                     else if (Mathf.Abs(sideDir) < Mathf.Abs(forwardDir))
    8.                         dodgeAngle = forwardDir * 180;
    But im not really happy about the code at all, it works but im not sure is this the right way with characterController.velocity ?? and i think the complete rotation code can be cleaner and easier to read. I really want to learn to code bettter code maybe you can give me a hit to make the rotation stuff better.

    i mean this code part.

    Code (CSharp):
    1.             // RotateRealtiveTo
    2.             if (playerInput.isRotationEnabled && isMoving) {
    3.                 if (moveMode == MoveMode.Directional) {
    4.                     targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
    5.                     angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothDamp);
    6.  
    7.                     transform.rotation = Quaternion.Euler(0f, angle, 0f);
    8.  
    9.                     //moveDirection = Quaternion.Euler(0, targetAngle, 0) * Vector3.forward;
    10.                     //moveDirection.Normalize();
    11.                 }
    12.  
    13.                 if (moveMode == MoveMode.Strafe) {
    14.                     //targetAngle = cameraTransform.eulerAngles.y;
    15.                     //transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothDamp);
    16.  
    17.                     targetAngle = cameraTransform.eulerAngles.y;
    18.                     angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothDamp);
    19.  
    20.                     Vector2 dir = new Vector2(transform.InverseTransformDirection(characterController.velocity).normalized.x, transform.InverseTransformDirection(characterController.velocity).normalized.z);
    21.                     var sideDir = dir.x;
    22.                     var forwardDir = dir.y;
    23.  
    24.                     if (Mathf.Abs(sideDir) > Mathf.Abs(forwardDir))
    25.                         dodgeAngle = sideDir * 90;
    26.                     else if (Mathf.Abs(sideDir) < Mathf.Abs(forwardDir))
    27.                         dodgeAngle = forwardDir * 180;
    28.  
    29.                     transform.rotation = Quaternion.Euler(0f, angle, 0f);
    30.                 }
    31.             }
    Screenshot_8.png

    Here a video how it looks the dodge
     
    Last edited: Dec 8, 2020