- Home /
How to Rotate the Player In Direction of Movement?
Hello all,
We've finally gotten the player to move left and right, and animation work perfectly. Our latest development is rotating the character in the direction of movement. When I move "right" the player is facing forward, but when I move left the character still faces to the right.
How may we resolve this issue?
Thanks in advance, and have a great day!
-Joshua4missions
using UnityEngine;
using System.Collections;
public class movementAlt : MonoBehaviour {
//Set Player Movement Speed
public float speed = 3.4f;
public float rotSpeed = 1.0f;
// Use this for initialization
void Start () {
//Set Starting Location
transform.position = new Vector3(5, 0, 0);
}
// Update is called once per frame
void Update () {
//Directional Movement
//Move Right
if(Input.GetKey(KeyCode.D)){
Debug.Log("Player Pressed the 'D' key");
transform.Translate(Vector3.forward * speed * Time.deltaTime);
transform.rotation(0, 270, 0);
animation.Play("Walk");
Debug.Log("Walk animation initiated");
}else {
Debug.Log("Player is not moving. Initiating 'Idle' state");
animation.Play("Idle");
}
//Move Left
if(Input.GetKey(KeyCode.A)){
Debug.Log("Player Pressed the 'A' key");
transform.Translate(Vector3.back * speed * Time.deltaTime);
transform.rotation(0, 90, 0);
animation.Play("Walk");
Debug.Log("Walk animation initiated");
}else {
Debug.Log("Player is not moving. Initiating 'Idle' state");
animation.Play("Idle");
}
//Attack
if(Input.GetMouseButtonDown(0)){
//Initiate Attack animation
animation.Play("Attack");
}else {
Debug.Log("Player is not attacking. Initiating 'Idle' state");
animation.Play("Idle");
}
}
}
Unfortunately, I'm still encountering this problem.
I'm still open to suggestions. Thanks in advance. :)
Always use transform.forward or transform.right if you are dealing with non global movement (e.g. player's movement) Vector3.Forward and the others are World Space Vectors so it will not change no matter what happen, but local space will.
Answer by zombience · Aug 08, 2013 at 03:00 PM
huh! I just dealt with this in a spherical environment last night. Quaternion.LookRotation() to the rescue!
using UnityEngine;
using System.Collections;
public class MoveLook : MonoBehaviour {
public float lookSpeed = 10;
private Vector3 curLoc;
private Vector3 prevLoc;
void Update ()
{
InputListen();
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - prevLoc), Time.fixedDeltaTime * lookSpeed);
}
private void InputListen()
{
prevLoc = curLoc;
curLoc = transform.position;
if(Input.GetKey(KeyCode.A))
curLoc.x -= 1 * Time.fixedDeltaTime;
if(Input.GetKey(KeyCode.D))
curLoc.x += 1 * Time.fixedDeltaTime;
if(Input.GetKey(KeyCode.W))
curLoc.z += 1 * Time.fixedDeltaTime;
if(Input.GetKey(KeyCode.S))
curLoc.z -= 1 * Time.fixedDeltaTime;
transform.position = curLoc;
}
}
Okay, this worked, except I can no longer play animations with this setup via: animation.Play();
oh hmm, i overlooked the fact that you were using animations. hmm, it doesn't seem like you're using mechanim, otherwise i'd say you can use blend trees to actually order your motion, turn left animations, turn right animations, etc.
if that's the case, what i've had to do in the past is create an empty object, make your animated character a child of that object, then animate character normally, and apply rotations to the parent object.
if you can get the rotation of the parent object tuned nicely with the animations, this can be perfectly convincing.
this also means that you'd have to apply all movement (forward, back, etc.) to the parent object as well.
if that doesn't help, let me know and i'd be happy to think of another way
also, how did you implement the code? it seems that you already are affecting the transform's rotation, so replacing that line with the Quaternion.LookRotation() should work the same way. I'm not clear on how that broke the animations.
I'm a little confused by your if statements. I was always under the impression that the syntax for an if statement is:
if (condition){
//Code to execute
}
The way you present it you totally eli$$anonymous$$ate the curly braces. As such there is no place to add the animation code.
Anyway, your help has been invaluable to anything I work on in the future. I've placed this project on hold due to a few random bugs. Example being code that worked at one compile gives errors next time I compile even with no changes.
I think I'll stick to 3D for now ins$$anonymous$$d of using a 3D application to make a 2D game(like this) lol.
oh, that's no big thing there! that's a simple syntax error. I apologize for putting that in there, since it can be confusing.
so the way an if statement works is, if you have ONLY ONE line of code following an if statement, that line of code binds to the if statement, and so you don't need curly braces.
if you want multiple lines of code, you $$anonymous$$UST surround your code with curly braces.
so:
void Update()
//correct for one statement:
if(comparison)
DoOneThing(); // execution is dependent on comparison
//incorrect for multiple statements
if(comparison)
DoOneThing(); // execution is dependent on comparison
DoOtherThing(); // will execute regardless of comparison
//correct for multiple statements
if(comparison)
{
DoOneThing(); // execution is dependent on comparison
DoOtherThing(); //execution is dependent on comparison
}
Answer by Kanox · Aug 10, 2013 at 03:37 AM
I was working on the same problem.
I had the issue where my object would revert to it's original position once I let go of the keys. I was able to fix this by containing everything inside of the key presses. This created the issue of the object rotating more than desired if I was going along a diagonal by holding down two buttons. I messed with the order of operations and now have an object rotating in the direction i'm heading no matter what combination of two buttons being pressed.
Not sure if there is a better way to write the code with fewer lines, but it works :)
Here's the final working code:
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
// How fast your object moves
public float moveSpeed;
// How fast your object will rotate in the direction of movement
public float rotationSpeed;
private Vector3 previousLocation;
private Vector3 currentLocation;
// Use this for initialization
void Start () {
moveSpeed = 100;
rotationSpeed = 5;
}
// Update is called once per frame
void Update () {
previousLocation = currentLocation;
currentLocation = transform.position;
if(Input.GetKey("w")&&Input.GetKey("a"))
{
currentLocation.z += moveSpeed * Time.fixedDeltaTime;
currentLocation.x -= moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("w")&&Input.GetKey("d"))
{
currentLocation.z += moveSpeed * Time.fixedDeltaTime;
currentLocation.x += moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("a")&&Input.GetKey("s"))
{
currentLocation.x -= moveSpeed * Time.fixedDeltaTime;
currentLocation.z -= moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("s")&&Input.GetKey("d"))
{
currentLocation.z -= moveSpeed * Time.fixedDeltaTime;
currentLocation.x += moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("w"))
{
currentLocation.z += moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("a"))
{
currentLocation.x -= moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("s"))
{
currentLocation.z -= moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
else if(Input.GetKey("d"))
{
currentLocation.x += moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
}
}
The code above functions, but I'm moving faster along the diagonals. I'm working on a different implementation at the moment.
Put the three direction variables into a vector3 and then normalize the vector, via: direction.Normalize() And you'll have consistent directional force. Unfortunately posting code from my phone is hard, so perhaps later I can put this in for you
Yeah, i've actually been reworking my code to be fewer lines and normalize the direction for consistency.
It's working, but I'm currently trying to figure out why it's not functioning 100% how I would like...
using UnityEngine;
using System.Collections;
public class Example : $$anonymous$$onoBehaviour {
// How fast your object moves
public float moveSpeed;
// How fast your object will rotate in the direction of movement
public float rotationSpeed;
private Vector3 previousLocation;
private Vector3 currentLocation;
private Vector3 moveDirection;
// Use this for initialization
void Start () {
moveDirection = new Vector3();
}
// Update is called once per frame
void Update () {
moveSpeed = 50;
rotationSpeed = 5;
previousLocation = currentLocation;
if(Input.Get$$anonymous$$ey("w")||Input.Get$$anonymous$$ey("a")||Input.Get$$anonymous$$ey("s")||Input.Get$$anonymous$$ey("d"))
{
if(Input.Get$$anonymous$$ey("w"))
{
moveDirection.z = 1;
}
if(Input.Get$$anonymous$$ey("a"))
{
moveDirection.x = -1;
}
if(Input.Get$$anonymous$$ey("s"))
{
moveDirection.z = -1;
}
if(Input.Get$$anonymous$$ey("d"))
{
moveDirection.x = 1;
}
}
else
{
moveSpeed = 0;
rotationSpeed = 0;
}
moveDirection.Normalize();
currentLocation = previousLocation + moveDirection * moveSpeed * Time.fixedDeltaTime;
transform.position = currentLocation;
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(currentLocation - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
}
The issue i'm running into with the code above is strange. Before pressing any key... If I just go back and forth between W and S or between A and D, it will rotate 180 degrees just fine. When I Go from W to A, or essentially go between the X and Z axis, it will take a while of holding down the direction key to get close to 90, 180, 270, or 0. It won't quite get to a straight line of movement holding one key down.
Holding down two keys two travel along a diagonal seems to work just fine.
It's hard to describe...
your question is different than that of the one above. you should post your own question, not post an "answer" to this question. requesting that the mods move it.
the problem is in your else/if structure. you're only allowing one value to be set at a time. so if you begin setting the z axis values, the else/if structure finds that case to be true, and skips setting anything else. reset the moveDirection vector3 to zero on each pass, so that you can clear any previous values.
public float moveSpeed;
public float rotationSpeed;
private Vector3 previousLocation;
private Vector3 moveDirection;
void Start()
{
}
void Update()
{
moveDirection = Vector3.zero;
previousLocation = transform.position;
if(input.Get$$anonymous$$ey($$anonymous$$eyCode.W))
{
moveDirection.z = 1;
}
if(input.Get$$anonymous$$ey($$anonymous$$eyCode.S))
{
moveDirection.z = -1;
}
if(input.Get$$anonymous$$ey($$anonymous$$eyCode.A))
{
moveDirection.x = -1;
}
if(input.Get$$anonymous$$ey($$anonymous$$eyCode.D))
{
moveDirection.z = 1;
}
transform.position = Vector3.Lerp(transform.position, transform.position + moveDirection.normalized, Time.fixedDeltaTime * moveSpeed);
transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.LookRotation(transform.position - previousLocation), Time.fixedDeltaTime * rotationSpeed);
}
Answer by jfmatheug · Mar 07, 2019 at 08:49 AM
This is the better way and shorter I kown so I share it to people with problems to solve this. I'm using Rigidbody velocity to move and previous and current position just to calculate look direction of the character.... movSpeed around 300f, lookSpeed around 8f. Note: I use FixedUpdate instead of Update
private void Move()
{
prevPos = curPos;
curPos = transform.position;
float hor = Input.GetAxisRaw("Horizontal") * Time.fixedDeltaTime;
float ver = Input.GetAxisRaw("Vertical") * Time.fixedDeltaTime;
curPos.x += hor;
curPos.z += ver;
Vector3 vel = new Vector3(hor, 0f, ver) * movSpeed;
rb.velocity = vel;
if (rb.velocity != Vector3.zero) {
animator.SetBool("Running", true);
transform.rotation = Quaternion.Normalize(Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(curPos - prevPos), Time.fixedDeltaTime * lookSpeed));
}
else { animator.SetBool("Running", false); }
}
Answer by badadam · Mar 08, 2019 at 09:03 PM
Add the script below to your gameobject
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//your other codes
transform.Rotate(0, -45, 0);
}
else if (Input.GetKeyDown(KeyCode.D))
{
//your other codes
transform.Rotate(0, 45, 0);
}
}