Search Unity

Get character to face direction of movement C#

Discussion in 'Scripting' started by 12doze12, Jun 19, 2013.

  1. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    This is the code I currently have to handle movement of a character:

    Code (csharp):
    1. if (Input.GetKey("w")){
    2.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + (float)0.1);
    3.         }
    4.         if (Input.GetKey("s")){
    5.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z - (float)0.1);
    6.         }
    7.         if (Input.GetKey("a")){
    8.             transform.position = new Vector3 (transform.position.x-(float)0.1, transform.position.y, transform.position.z);
    9.         }
    10.         if (Input.GetKey("d")){
    11.             transform.position = new Vector3 (transform.position.x+(float)0.1, transform.position.y, transform.position.z);
    12.         }

    However the character always faces the same direction and not where it goes.

    For that I'm trying to use:

    Code (csharp):
    1. transform.LookAt(new Vector3());
    However I can't get it to work.

    One of the ideas I had was to get vector coordinates of the current and the previous position of X and Z and put them inside that new Vector3 while Y=0 but I always get spazing out movement and weird physics.

    PS: I'm using a Rigidbody
     
  2. ar0nax

    ar0nax

    Joined:
    May 26, 2011
    Posts:
    485
    hi there, instead of (float)0.1 use 0.1f and to make the character look at the direction he's moving look into Transforms, Vector3's Eulers and so on. The easiest way to do it in your case is to modify the transform's rotation to make it look from 90 to 90 degrees to the direction it's walking.
    Code (csharp):
    1.  
    2. transform.eulerAngles = new Vector3(0, 90, 0);
    3. //or
    4. transform.eulerAngles = new Vector3(0, 0, 0);
    5. //and so on
    6.  
    Also your movement it's not FrameRate dependable, which means that on slow hardware it'll move way slower than on other new devices. use Time.deltaTime as a multiplier for your movement modifications.
    Code (csharp):
    1.  
    2. //add the rotation change here
    3. transform.position = new Vector3 (transform.position.x-Speed, transform.position.y, transform.position.z) * Time.deltaTime;
    4.  
     
    Last edited: Jun 19, 2013
    LimeyMimey likes this.
  3. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    Isn't 90 too much, I think 45 would be much better.
     
  4. ar0nax

    ar0nax

    Joined:
    May 26, 2011
    Posts:
    485
    this is, you are moving left, right, forward and backwards. that's 90 degrees rotation.
     
  5. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    oh I see, but won't that look weird if I walk diagonally?
     
  6. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    Here is one way to resolve this:

    1. At the beginning of the move calculate an angle between your forward vector and (position_you_are_moving_towards - position_of_your transform). See the code I usually use for that.
    2. Rotate your transform by that angle. (transform.Rotate(up, angle_from_step_one);)

    Code (csharp):
    1.     public static float getAngle(Vector3 fr, Vector3 to, Vector3 up)
    2.     {
    3. // http://answers.unity3d.com/questions/24983/how-to-calculate-the-angle-between-two-vectors.html      
    4.        
    5.         // the vector perpendicular to referenceForward (90 degrees clockwise)
    6.         // (used to determine if angle is positive or negative)
    7.         Vector3 referenceRight= Vector3.Cross(up, fr);
    8.          
    9.         // Get the angle in degrees between 0 and 180
    10.         float angle = Vector3.Angle(to, fr);
    11.      
    12.         // Determine if the degree value should be negative. Here, a positive value
    13.         // from the dot product means that our vector is the right of the reference vector
    14.         // whereas a negative value means we're on the left.
    15.         float sign = (Vector3.Dot(to, referenceRight) > 0.0f) ? 1.0f: -1.0f;
    16.      
    17.         float finalAngle = sign * angle;
    18.        
    19.         return finalAngle;
    20.        
    21.     }
    22.  
     
  7. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    Looks like a good idea, thanks, going to give it a go.
     
  8. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    So it's something like this for move up:

    Code (csharp):
    1. transform.Rotate(Vector3.up, Vector3.Angle(Vector3.forward, new Vector3(transform.position.x,transform.position.y,transform.position.z) -  new Vector3(transform.position.x,transform.position.y,transform.position.z + (float)0.1)));
     
  9. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    No.

    1. You need to use the forward vector of your character transform.
    2. Don't use Vector3.Angle - it doesn't take care of the sign - use the code I provided earlier.
     
  10. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    With gravity activated it goes to (0,0,0) and then moves and if I disable gravity it just sits in (0,0,0), I get the same result using my code
     
  11. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    any ideas ?
     
  12. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    Sorry. I'm not sure I understand. Are you saying that when you try to move your character now it just goes to (0,0,0) and doesn't move from there? If yes, can you post you current code that performs movement and rotation?
     
  13. NikoBusiness

    NikoBusiness

    Joined:
    May 6, 2013
    Posts:
    289
    transform.translate is the best solution for you!
     
  14. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    if I use your code or my version I get the same result but I tried to different things:

    - gravity on - when I move the character goes to (0,0,0) and then moves quickly in a random direction (probably has to do with the terrain been at (0,0,0) so the object get's sliced by it)

    - gravity off - when I move the character it goes to (0,0,0) and stops.

    My version:

    Code (csharp):
    1.         if (Input.GetKey("w")){
    2.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + (float)0.1)* Time.deltaTime;
    3.             transform.Rotate(Vector3.up, Vector3.Angle(Vector3.forward, new Vector3(transform.position.x,transform.position.y,transform.position.z) -  new Vector3(transform.position.x,transform.position.y,transform.position.z + (float)0.1)));
    4.         }
    5.         if (Input.GetKey("s")){
    6.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z - (float)0.1)* Time.deltaTime;
    7.             transform.Rotate(Vector3.up, Vector3.Angle(Vector3.forward, new Vector3(transform.position.x,transform.position.y,transform.position.z) -  new Vector3(transform.position.x,transform.position.y,transform.position.z - (float)0.1)));
    8.         }
    9.         if (Input.GetKey("a")){
    10.             transform.position = new Vector3 (transform.position.x-(float)0.1, transform.position.y, transform.position.z)* Time.deltaTime;
    11.             transform.Rotate(Vector3.up, Vector3.Angle(Vector3.forward, new Vector3(transform.position.x,transform.position.y,transform.position.z) -  new Vector3(transform.position.x + (float)0.1,transform.position.y,transform.position.z )));
    12.         }
    13.         if (Input.GetKey("d")){
    14.             transform.position = new Vector3 (transform.position.x+(float)0.1, transform.position.y, transform.position.z)* Time.deltaTime;
    15.         transform.Rotate(Vector3.up, Vector3.Angle(Vector3.forward, new Vector3(transform.position.x,transform.position.y,transform.position.z) -  new Vector3(transform.position.x - (float)0.1,transform.position.y,transform.position.z)));
    16.         }
    Your code and my code have the same result.
     
  15. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    Can you be more specific ? I may be wrong but doesn't transform.translate deal only with postion?
     
  16. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    12doze12 - the main problem with your code is that it multiplies your new position by deltaTime. That puts your position always very close to (0,0,0). Your code should look something like this (assuming 10 as your speed):

    Code (csharp):
    1.        if (Input.GetKey("w")){
    2.             Vector3 pos = new Vector3 (transform.position.x, transform.position.y, transform.position.z + 10f * Time.deltaTime);
    3.             transform.Rotate(Vector3.up, Vector3.Angle(transform.forward, pos - transform.position);
    4.             transform.position = pos;
    5.         }
    Also, you are still not using the getAngle method I listed earlier :) . As I said, Vector3.Angle is not going to work 100% of the time.
     
  17. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    It works but the orientations are wrong:

    -move left - point down
    -move right - point up
    -move up - point right
    -move down - point left

    Also this doesn't work diagonally ...
     
  18. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Why don't you build a Vector3 instead of applying to transform.position at each step and then do a transform.LookAt(destination) before moving there?
     
  19. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    This is the code and it's now working, however it still has the problem of only having 4 orientations:

    Code (csharp):
    1. if (Input.GetKey("w")){
    2.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + (float)0.1);
    3.             transform.LookAt(new Vector3(transform.position.x,5,transform.position.z - 0.1F));
    4.         }
    5.         if (Input.GetKey("s")){
    6.             transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z - (float)0.1);
    7.             transform.LookAt(new Vector3(transform.position.x,5,transform.position.z + 0.1F));
    8.         }
    9.         if (Input.GetKey("a")){
    10.             transform.position = new Vector3 (transform.position.x-(float)0.1, transform.position.y, transform.position.z);
    11.             transform.LookAt(new Vector3(transform.position.x + 0.1F,5,transform.position.z ));
    12.         }
    13.         if (Input.GetKey("d")){
    14.             transform.position = new Vector3 (transform.position.x+(float)0.1, transform.position.y, transform.position.z);
    15.             transform.LookAt(new Vector3(transform.position.x - 0.1F,5,transform.position.z));
    16.         }
    17.        
     
  20. 12doze12

    12doze12

    Joined:
    Mar 17, 2013
    Posts:
    57
    Probably not the best solution but I made the same for diagonals (still doesn't looks smooth obviusly):

    Code (csharp):
    1. if (Input.GetKey("w")  Input.GetKey("d")){
    2.             transform.position = new Vector3 (transform.position.x + (float)0.1, transform.position.y, transform.position.z + (float)0.1);
    3.             transform.LookAt(new Vector3(transform.position.x - 0.1F ,5,transform.position.z - 0.1F));
    4.         }
    5.         if (Input.GetKey("w")  Input.GetKey("a")){
    6.             transform.position = new Vector3 (transform.position.x - (float)0.1, transform.position.y, transform.position.z + (float)0.1);
    7.             transform.LookAt(new Vector3(transform.position.x + 0.1F ,5,transform.position.z - 0.1F));
    8.         }
    9.         if (Input.GetKey("s")  Input.GetKey("a")){
    10.             transform.position = new Vector3 (transform.position.x - (float)0.1, transform.position.y, transform.position.z - (float)0.1);
    11.             transform.LookAt(new Vector3(transform.position.x + 0.1F ,5,transform.position.z + 0.1F));
    12.         }
    13.         if (Input.GetKey("s")  Input.GetKey("d")){
    14.             transform.position = new Vector3 (transform.position.x + (float)0.1, transform.position.y, transform.position.z - (float)0.1);
    15.             transform.LookAt(new Vector3(transform.position.x - 0.1F ,5,transform.position.z + 0.1F));
    16.         }
    Anyway, thanks to everyone that helped me, especially cdevl. Thanks, :)
     
  21. LimeyMimey

    LimeyMimey

    Joined:
    Dec 21, 2020
    Posts:
    7
    ok so ive been trying for hours (im very new to c#, only had watched the how to make a game series and started the junior programming course on the unity website) and this worked so i cant say how happy i was to see it work so thank you for teaching people in the ways of code and bettering the community you are awesome.