Is there a nice easy way to add rotation into this script ? Basically, rotate the object / cube in the direction of the movement, best practice, best method ?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePlayer : MonoBehaviour
{
[Header("Player Speed")]
public float playerSpeed = 10;
private Rigidbody playerBody;
void Start()
{
playerBody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
float hAxis = Input.GetAxis("Horizontal");
float vAxis = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(hAxis, 0, vAxis) * playerSpeed * Time.deltaTime;
playerBody.MovePosition(transform.position + movement);
}
void OnDrawGizmos()
{
Gizmos.color = Color.white;
Vector3 direction = transform.TransformDirection(Vector3.forward) * 5;
Gizmos.DrawRay(transform.position, direction);
}
}
You can use Mathf.Atan2() to get the direction of an arbitrary Vector2 direction. It comes back in radians from -pi to +pi, so you can multiply it by Mathf.Rad2Deg to get degrees.
Once you have degrees you can either snap or progressively turn yourself to face that heading.
Unless you need the rigidbody to truly rotate (use .MoveRotation()), you may want to just use this angle to drive a child pivot point.
Thanks, I’ve actually been looking at a lot of alternative methods, mostly transform based ( which I’ve also heard can cause untold problems ), but was curious if there was a ‘go to’ method when dealing directly with rigidbodies, I’ll post again when I think I’ve come up with a decent solution.
Not really. Each approach will be more- or less-suitable for a particular application. Just differences in how you parent everything together will have profound impacts on the solution you choose.
The good part is that it is software: try an approach, if it works, great, if it sorta works, iterate and fix it. It’s soft.
I added 1 line of code, the movement is snappy, but I now have a problem that if I let go of the keyboard, the player cube ‘snaps’ to the x or z axis, I’d rather my player cube stayed in the orientation I left it at, so still work to do…
transform.LookAt(transform.position + new Vector3(movement.x, 0, movement.z));
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveRB : MonoBehaviour
{
[Header("Player Speed")]
public float playerSpeed = 10.0f;
private Rigidbody playerRigidbody;
void Start()
{
playerRigidbody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
float hAxis = Input.GetAxis("Horizontal");
float vAxis = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(hAxis, 0, vAxis) * playerSpeed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position + movement);
transform.LookAt(transform.position + new Vector3(movement.x, 0, movement.z));
}
void OnDrawGizmos()
{
Gizmos.color = Color.white;
Vector3 direction = transform.TransformDirection(Vector3.forward) * 5;
Gizmos.DrawRay(transform.position, direction);
}
}
That’s a very common issue with instant rotations with keyboard movement - players will never be able to let go of two keys on the same frame, so they won’t be able to stand exactly facing in a 45 degree angle.
If you want to fix that, you can solve that in two ways:
Check if it happens, and undo it. Basically, when the player lets go of the last button, check how long it’s since they were moving diagonally, and then snap the player back to diagonal if it’s less than a certain threshold.
Fix it by not snapping rotation directly, but instead moving it over time.
Finally, you probably want to set the rigidbody’s rotation, not the transform.position. Getting a rotation quaternion from a movement direction is really easy:
if (movement.sqrMagnitude > 0.001f) { // If-check as a rotation that looks in no direction isn't valid
Quaternion forwardsRotation = Quaternion.LookRotation(movement);
rigidbody.MoveRotation(forwardsRotation);
}