Search Unity

Face forward based on rigid body velocity

Discussion in 'Scripting' started by Hilm, Mar 20, 2011.

  1. Hilm

    Hilm

    Joined:
    Nov 2, 2007
    Posts:
    338
    Hey,
    So I've done a forum search without any luck, but essentially what I'm trying to do is make a rigidbody (locked in a 2d plane/ gameplay) constantly face the direction it is traveling...

    I've played around with using eular angles but the result is that I get a ton of jumping around in the rotation and it dosen't really work very well.

    It seems like something that is probably used a lot, therefore does anyone have any quick sample code (likely using Quantarions rather than eular angles) which will do the job?

    Thanks in advance,
    - Adam
     
  2. Loftless

    Loftless

    Joined:
    Mar 20, 2011
    Posts:
    16
    this.transform.rotation = Quaternion.LookRotation(velocity, Vector3.up); //Make the object always face the direction it is moving in

    that should hopefully be the code you're looking for. I did a few tests with it, it seemed to work fine.

    Quick Edit: This is just raw turn code, nothing fancy like gradually turning towards location. If you need that let me know, I have it around here somewhere.
     
  3. eddie987321

    eddie987321

    Joined:
    Apr 8, 2012
    Posts:
    3
    I've met with a similar problem and the script works fine apart from some visual bugs which I can't seem to fix.
    Firstly when I start the game, the player is rotated forward 90 degrees so that they're facing the floor until movement is applied. Secondly when the player comes to a rest (excluding the initial one) it starts twitching. My code is as follows:

    velocity = rigidbody.velocity;
    if (velocity != Vector3.zero) {
    transform.rotation = Quaternion.LookRotation(velocity, Vector3.up);
    }

    Any help would be much appreciated :)
     
  4. GargerathSunman

    GargerathSunman

    Joined:
    May 1, 2008
    Posts:
    1,571
    Try:

    if (velocity.magnitude > .01) {
     
  5. eddie987321

    eddie987321

    Joined:
    Apr 8, 2012
    Posts:
    3
    Thanks for the reply. It works but when my player bounces off a wall and then comes to rest it starts spinning in circles (clockwise or anticlockwise).

    Edit: It rotates clockwise/anticlockwise on its Y axis.
     
  6. eddie987321

    eddie987321

    Joined:
    Apr 8, 2012
    Posts:
    3
    Okay I've been trying to debug this for a while now. Apparently once the "if" condition isn't fulfilled anymore the player assumes the rotation it would have had if it weren't modified by the script. So basically once the player collides into a wall, normally it would start spinning wildly either clockwise or anticlockwise (since I've locked its X and Z rotation), but since the script it telling the object to face the direction of its current velocity, there's no visual bug until the script stops acting on the player (ie. when the player falls below 0.01 velocity).

    Any ideas on how to fix this? I'm thinking it'd be something like stopping the object from rotation when it collides with something but I have no idea how I would do this. Is there some alternative solution to having the player face the direction its travelling in?

    Edit: Nevermind! I can't believe how stupid I was. I can just lock the Y rotation. The player can still rotate since the rotation is applied through script and not by the physics and collisions in game.
     
    Last edited: Apr 8, 2012
  7. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    Why do you want to use the velocity? Is your "player" physic driven? Physic driven controlls are generally problematic, that's why you have the CharacterController.Move(...) oder Transform.Translate(...) methods.

    Code (csharp):
    1.  
    2. Vecto3 direction = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    3. direction *= 5.0f; // apply speed
    4.  
    5. // move the character in this direction
    6. characterController.Move(direction);
    7.  
    8. // Change the forward direction of the player into the direction he is running
    9. transform.forward = direction;
    10.  
     
  8. Beugnen

    Beugnen

    Joined:
    Oct 4, 2012
    Posts:
    6
    agreed, though sqrMagnitude is faster ;)
     
  9. muzboz

    muzboz

    Joined:
    Aug 8, 2012
    Posts:
    110
    For anyone ending up at this page based just on the subject heading (such as me!)...

    I wanted a crossbow bolt to LookAt (the way it's RigidBody is moving), so that the bolt would arc through the air as it goes up, and comes down, and also so that the bolt would visually look like it changed direction if it bounces off a surface.

    I ended up with this line of code that worked perfectly for me...

    transform.LookAt(transform.position + rb.velocity);



    Further info for anyone interested, but really not necessary if the above line works for you! :D

    Note that the transform.LookAt function has 4 different variations, depending on what you pass in to it.

    The one I use takes in just a WorldSpace position to LookAt. So I simply pass in a position that is where the bolt is, + it's velocity vector.


    For this particular case, I made a game object called Bolt, which has the Rigid Body and the BoltBehaviour.cs script. I didn't want to be rotating the Rigid Body itself. I just wanted to let it do it's thing.

    So I made another child game object called "Mesh" which has the actual bolt Mesh and the Collider on it. I could then rotate this mesh and collider, without affecting the Rigid Body underlying it on the parent.

    - Bolt (BoltBehaviour.cs, Rigid Body)
    - - Mesh (Mesh, Collider)

    So the Bolt flies through the air, and the script updates the Mesh each frame to LookAt (transform + velocity).

    ...

    PS: I have another function that would detect if the bolt has "come to a stand still" (by moving slowly enough), after which point, it no longer uses this LookAt function, as I wanted the bolt to become sort of an inert object at that point. So it just acts like any other "dumb" physics object at that point.
     
    Last edited: Jan 6, 2022