I currently have the following class. The class is supposed to be a custom character controller that allows the player to walk on non-horizontal surfaces, and so far most of it has been working, except for direction-based movement.
using UnityEngine;
using System.Collections;
namespace Normal
{
/// <summary>
/// This class is responsible for managing the various aspects of the player,
/// from simple movement to mesh alignment.
/// </summary>
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
public float RotationTransitionSpeed = 1.0f;
public float Sensitivity = 2.0f;
public float MovementSpeed = 5.0f;
public float RaycastDistance = 10.0f;
public float GravityForce = 9.8f;
public Vector3 GravityVector = new Vector3(0, -1, 0);
private Quaternion _TargetRotation;
private float _VerticalCameraRotation;
private Vector3 _MovementDistance;
private Vector3 _MovementVelocity;
private Rigidbody _Rigidbody;
/// <summary>
/// Apply movement to the player object based on specific key inputs. The player can currently
/// move forwards, backwards, left and right.
/// </summary>
public void ApplyMovement()
{
Vector3 movementDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")).normalized;
Vector3 movementVector = movementDirection * this.MovementSpeed * Time.deltaTime;
this.transform.Translate(movementVector);
}
/// <summary>
/// Apply rotation to the player based on the normal of the face they're
/// "above". This function will also set the gravity of the player accordingly.
/// </summary>
public void ApplyRotation()
{
// Apply rotation to the player and the camera objects based on the movement of
// the mouse cursor.
Camera.main.transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * this.Sensitivity);
this._VerticalCameraRotation += Input.GetAxis("Mouse Y") * this.Sensitivity;
this._VerticalCameraRotation = Mathf.Clamp(this._VerticalCameraRotation, -60, 60);
Camera.main.transform.localEulerAngles = new Vector3(
Vector3.left.x * this._VerticalCameraRotation,
Camera.main.transform.localEulerAngles.y,
0
);
// Apply rotation to the entire player object based on where they are walking
// on a specific mesh.
RaycastHit raycastHit;
if(Physics.Raycast(this.transform.position, -this.transform.up, out raycastHit))
{
this._TargetRotation = Quaternion.FromToRotation(Vector3.up, raycastHit.normal);
this.GravityVector = -raycastHit.normal;
}
this.transform.rotation = Quaternion.Lerp(
this.transform.rotation,
this._TargetRotation,
Time.deltaTime * this.RotationTransitionSpeed
);
}
/// <summary>
/// Apply a gravity force to the player based on the currently set gravitational
/// force. Gravitational force direction is determined based on the normal that
/// the player is "above".
/// </summary>
public void ApplyGravity()
{
this._Rigidbody.AddForce(this.GravityVector * this.GravityForce * this._Rigidbody.mass);
}
/// <summary>
/// FixedUpdate is called a set amount of times per frame in sync with the physics engine.
/// </summary>
public void FixedUpdate()
{
this.ApplyGravity();
}
/// <summary>
/// Update is called once per frame.
/// </summary>
public void Update()
{
this.ApplyRotation();
this.ApplyMovement();
}
/// <summary>
/// Start is called once.
/// </summary>
public void Start()
{
this._Rigidbody = this.GetComponent<Rigidbody>();
}
}
}
Ideally, I’d like to have the player move forward relative to the direction the camera is facing, but I cannot for the life of me figure out how to do this. Is it possible?