I’m creating a rigidbody-based character controller.
I’m trying to do what the speaker describes at 5:05
What I have so far sort of works but there are multiple issues.
The acceleration (acc vector3) never goes back to zero, which results in jerking in one place when the character is stationary.
I can’t seem to ensure that the character returns to an upright position.
I tried using rigidbody.moverotation but I keep getting lost trying to figure out the vectors and quaternions (not my strong suite).
I guess I should consolidate the addtorque lines into one, but that would require figuring out the correct vector to use as well.
Can you please point me in the right direction on how to improve?
Here’s my current code:
using UnityEngine;
using System.Collections;
public class Gen3_3PC : MonoBehaviour {
float verticalInput, horizontalInput, sWangleCounter;
public float angle;
public Vector3 velocity, lastVelocity;
Transform mainCamera;
Rigidbody rb;
Animator anim;
public Vector3 move;
Vector3 lastPosition;
public float walkSpeed, runSpeed, acceleration, stepDistance;
public Vector3 acc;
// Use this for initialization
void Start () {
verticalInput = 0;
horizontalInput = 0;
rb = GetComponent<Rigidbody> ();
anim = GetComponent<Animator> ();
mainCamera = Camera.main.transform;
lastPosition = Vector3.zero;
sWangleCounter = 0.0f;
lastVelocity = Vector3.zero;
}
// Update is called once per frame
void Update ()
{
GetInputs ();
}
void FixedUpdate ()
{
CalcMove ();
rb.AddForce (move, ForceMode.Acceleration);
CalcAngle ();
CalcAcc ();
rb.AddTorque (transform.forward * acc.x * 2, ForceMode.Acceleration);
rb.AddTorque (transform.right * acc.z * 2, ForceMode.Acceleration);
rb.AddTorque (0, angle * 10, 0, ForceMode.Acceleration);
rb.AddTorque (-rb.angularVelocity, ForceMode.VelocityChange);
CalcRunStage ();
anim.SetFloat("speed", Mathf.Sqrt((rb.velocity.x * rb.velocity.x) + (rb.velocity.z * rb.velocity.z)));
}
void GetInputs()
{
verticalInput = Input.GetAxis ("Vertical");
horizontalInput = Input.GetAxis ("Horizontal");
}
void CalcMove()
{
move = Vector3.zero;
if (verticalInput > 0)
move += Vector3.Scale (mainCamera.forward, new Vector3 (1, 0, 1)).normalized;
else if (verticalInput < 0)
move -= Vector3.Scale (mainCamera.forward, new Vector3 (1, 0, 1)).normalized;
if (horizontalInput > 0)
move += Vector3.Scale (mainCamera.right, new Vector3 (1, 0, 1)).normalized;
else if (horizontalInput < 0)
move -= Vector3.Scale (mainCamera.right, new Vector3 (1, 0, 1)).normalized;
move = move.normalized * acceleration;
}
void CalcRunStage()
{
lastPosition = new Vector3 (lastPosition.x, 0f, lastPosition.z);
Vector3 currentPosition = new Vector3 (transform.position.x, 0f, transform.position.z);
float dist = Vector3.Distance (lastPosition, currentPosition);
float turnAngle = (dist / (2 * Mathf.PI * 1)) * 360f; //PI * 1 should be PI * radius, we just chose radius to be 1
sWangleCounter += turnAngle;
if (sWangleCounter > stepDistance)
sWangleCounter = 0.0f;
anim.SetFloat ("runstage", (sWangleCounter / stepDistance));
if (anim.GetFloat ("runstage") > 1.0f)
anim.SetFloat ("runstage", 0);
lastPosition = currentPosition;
}
void CalcAngle()
{
angle = Vector3.Angle (transform.forward, rb.velocity.normalized);
if (Vector3.Cross (transform.forward, rb.velocity.normalized).y < 0)
angle = -angle;
if (rb.velocity == Vector3.zero)
angle = 0.0f;
}
void CalcAcc()
{
velocity = transform.InverseTransformVector(rb.velocity);
acc = (velocity - lastVelocity) / Time.fixedDeltaTime;
lastVelocity = velocity;
}
}