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

Moving on x axis and turning 180 degrees on y axis

Discussion in 'Scripting' started by Flapman, Jun 11, 2021.

  1. Flapman

    Flapman

    Joined:
    Aug 15, 2010
    Posts:
    84
    Hello all,

    I have been beating my head against the wall trying to figure this out. I looked at lots of blog posts and help files and still can't make it work.

    I have a character I am moving left and right on the x axis. I want to move forward (left or right keys) then when I press the opposite left or right key, the player turns around smoothly 180 degrees. It seems that would be a simple process. I just can't seem to write the correct code to make it happen.

    In the follow script, the character just keep spinning in the direction of the left or right key press. Please help. :)

    Thanks in advance.

    note: t_speed is a float for turnspeed

    Code (CSharp):
    1.    // Moves player except while jumping
    2.     void MovePlayer()
    3.     {
    4.         moveX = Input.GetAxis("Horizontal");
    5.    
    6.  
    7.         if (Input.GetKey(KeyCode.LeftArrow))
    8.         {
    9.             //Rotate the character about the Y axis 180 degrees then move on x axis in the negative direction
    10.             transform.Rotate(new Vector3(0, -90, 0) * Time.deltaTime * t_speed);
    11.             playerRb.AddForce(Vector3.left * moveX * speed * speedModifier * Time.deltaTime);
    12.         }
    13.  
    14.         if (Input.GetKey(KeyCode.RightArrow))
    15.         {
    16.             //Rotate the character about the Y axis 180 degrees then move on x axis in the positive direction
    17.             transform.Rotate(new Vector3(0, -90, 0) * Time.deltaTime * t_speed);
    18.             playerRb.AddForce(Vector3.right * moveX * speed * speedModifier * Time.deltaTime);
    19.         }
     
    Last edited: Jun 11, 2021
  2. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,108
    You must change approach a bit. I assume MovePlayer() is called every Update(), so currently you check every frame if player holds left or right and then you move plus rotate, but the thing is that transform.Rotate will turn the object by given angle, but it does not care if its already turned correctly or not, it will stack every frame.
    For starters you should try for example RotateTowards, it rotates quaternion by a provided angle towards given direction, but it will not overshoot.
    It will be something like this:
    Code (CSharp):
    1.  
    2. transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(Vector3.right), Time.deltaTime * t_speed);
    3.  
    Obviously this is not the only possible way to do this.
     
    Flapman likes this.
  3. Flapman

    Flapman

    Joined:
    Aug 15, 2010
    Posts:
    84
    Thanks. So using this method, could I set the specific degree target direction for both the left and right keys? This is I what I did with your suggestion.

    Code (CSharp):
    1.  // Moves player except while jumping
    2.     void MovePlayer()
    3.     {
    4.         moveX = Input.GetAxis("Horizontal");
    5.      
    6.  
    7.         if (Input.GetKey(KeyCode.LeftArrow))
    8.         {
    9.             //Rotate the character about the Y axis 180 degrees then move on x axis in the negative direction
    10.             transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(Vector3.left), Time.deltaTime * t_speed);
    11.             playerRb.AddForce(Vector3.left * moveX * speed * speedModifier * Time.deltaTime);
    12.         }
    13.  
    14.         if (Input.GetKey(KeyCode.RightArrow))
    15.         {
    16.             //Rotate the character about the Y axis 180 degrees then move on x axis in the positive direction
    17.             transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(Vector3.right), Time.deltaTime * t_speed);
    18.             playerRb.AddForce(Vector3.right * moveX * speed * speedModifier * Time.deltaTime);
    19.         }
    20.  
     
    Last edited: Jun 11, 2021
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,108
    You can set any direction. RotateTowards just lerps between two directions and the second one can by anything you want. In my example I just constructed rotation from direction vector, but you can put there any quaternion for example:
    Code (CSharp):
    1. Quaternion.Euler(0, 90, 0);
    https://docs.unity3d.com/ScriptReference/Quaternion.Euler.html
     
  5. Flapman

    Flapman

    Joined:
    Aug 15, 2010
    Posts:
    84
    Thanks again. Can you let me know if I got this right. The character still does not turn around and seems to lock in place.

    Code (CSharp):
    1.  // Moves player except while jumping
    2.     void MovePlayer()
    3.     {
    4.         moveX = Input.GetAxis("Horizontal");
    5.      
    6.  
    7.         if (Input.GetKey(KeyCode.LeftArrow))
    8.         {
    9.             //Rotate the character about the Y axis 180 degrees then move on x axis in the negative direction
    10.             transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0, 90, 0), Time.deltaTime * t_speed);
    11.             //playerAnim.SetBool("TurnL", true);
    12.             playerRb.AddForce(Vector3.left * moveX * speed * speedModifier * Time.deltaTime);
    13.             playerAnim.SetFloat("Speed", moveX);
    14.  
    15.         }
    16.  
    17.         if (Input.GetKey(KeyCode.RightArrow))
    18.         {
    19.             //Rotate the character about the Y axis 180 degrees then move on x axis in the positive direction
    20.          
    21.             transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0, 90, 0), Time.deltaTime * t_speed);
    22.             //playerAnim.SetBool("TurnR", true);
    23.             //transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(Vector3.right), Time.deltaTime * t_speed);
    24.             playerRb.AddForce(Vector3.right * moveX * speed * speedModifier * Time.deltaTime);
    25.             playerAnim.SetFloat("Speed", moveX);
    26.  
    27.         }
     
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,108
    The first one should be probably:
    Code (CSharp):
    1. Quaternion.Euler(0, -90, 0)
    You must determine world space direction for both of them, they can't be the same for left and right.
    The line above means "create rotation -90 deg around Y axis", it's the same as typing angles in transform component.
     
    Flapman likes this.
  7. Flapman

    Flapman

    Joined:
    Aug 15, 2010
    Posts:
    84
    Thanks. I appreciate it a lot. I'll take a look at that.

    My frustration at this point is that my Character Controller has so many issues and I am wondering if I should start from scratch. lol