derlin of Unity
4/25/2017 - 12:31 PM

Script to control a rigidbody character. It is adapted from http://wiki.unity3d.com/index.php?title=RigidbodyFPSWalker Main changes: - add

Script to control a rigidbody character. It is adapted from http://wiki.unity3d.com/index.php?title=RigidbodyFPSWalker

Main changes:

  • add animator (should have at least two parameters: Forward and Jump
  • make the body rotate in the direction of the movement
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]

// taken and adapted from http://wiki.unity3d.com/index.php?title=RigidbodyFPSWalker
public class RigidBodyControllerSimple : MonoBehaviour
{
    public float speed = 10.0f;
    public float gravity = 10.0f;
    public float maxVelocityChange = 10.0f;
    public bool canJump = true;
    public float jumpHeight = 2.0f;
    // what to rotate in the direction of the move
    // by default, rotations are locked. Workaround:
    // put the rigidbody in the parent and the rendering 
    // components of the body in a child GameObject.
    public GameObject body;

    private bool grounded = false;
    private Rigidbody rigidBody;
    private Animator animator;


    private bool jumping = false, torporGround = false; // for death type

    void Awake()
    {
        rigidBody = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();

        rigidBody.freezeRotation = true;
        rigidBody.useGravity = false;
    }

    void FixedUpdate()
    {

        if (grounded)
        {
            jumping = false;
            animator.SetFloat("Jump", 0f);
            // Calculate how fast we should be moving
            Vector3 targetVelocity = Vector3.zero;

            // get input and rotate accordingly
            targetVelocity = getMoveDirection(); 
            rotateBody(targetVelocity);

            // compute actual velo ity
            targetVelocity = transform.TransformDirection(targetVelocity);
            targetVelocity *= speed;

            animator.SetFloat("Forward", targetVelocity.magnitude);
            // Apply a force that attempts to reach our target velocity
            Vector3 velocity = rigidBody.velocity;
            Vector3 velocityChange = (targetVelocity - velocity);
            velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
            velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
            velocityChange.y = 0;
            rigidBody.AddForce(velocityChange, ForceMode.VelocityChange);
            //rigidbody.MovePosition(rigidbody.position + targetVelocity * Time.deltaTime);
            // Jump
            if (canJump && Input.GetButton("Jump"))
            {
                jumping = true;
                animator.SetFloat("Jump", 1f);
                rigidBody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
            }
        }

        // We apply gravity manually for more tuning control
        rigidBody.AddForce(new Vector3(0, -gravity * rigidBody.mass, 0));

        grounded = false;
    }

    void OnCollisionStay()
    {
        grounded = true;
    }

    float CalculateJumpVerticalSpeed()
    {
        // From the jump height and gravity we deduce the upwards speed 
        // for the character to reach at the apex.
        return Mathf.Sqrt(2 * jumpHeight * gravity);
    }

    Vector3 getMoveDirection()
    {
        // return new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        float h = CrossPlatformInputManager.GetAxis("Horizontal");
        float v = CrossPlatformInputManager.GetAxis("Vertical");
        Vector3 m_CamForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
        return v * m_CamForward + h * Camera.main.transform.right;
    }

    void rotateBody(Vector3 direction)
    {
        if (direction == Vector3.zero) return;
        //instead of body.transform.LookAt(transform.position + direction);  
        // so it is smoother    
        body.transform.rotation =
            Quaternion.Slerp(body.transform.rotation, Quaternion.LookRotation(direction.normalized), 0.3f);
    }
}