rigidbody controller

these buttons are required in project input settings

Forward
Back
Left
Right
Run
Jump
LookAround
ToggleCrouch
Mouse X
Mouse Y

attach to a capsule and set camera that is its child in the inspector

using UnityEngine;
using System.Collections;

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

public class Rbctrl : MonoBehaviour
{
    CapsuleCollider capsCollider;
    float crouchHeight,standHeight;
   
    Rigidbody rb;
   
    public Transform cam;
    public bool invertY;
   
    public float acceleration=6,deceleration=6,maxForwardSpeed=22,maxBackSpeed=18,maxStrafeSpeed=18,runModifier=18,crouchModifier=.6f,
   
    rotSpeed=4,minRotX=-90,maxRotX=90,minRotY=-90,maxRotY=90,
   
    rigidbodyDrag=5, speedMultiplierX=1,speedMultiplierZ=1,
   
    minJumpPower=9,maxJumpPower=9,
    jumpMultiplierX=.01f,jumpMultiplierY=.6f,jumpMultiplierZ=.01f,
   
    groundCheckDistance = .1f,
    stickToGroundHelperDistance=.05f,
   
    camBobX=.006f,camBobY=.008f,camBobZ=0,camReturnSpeed=.04f,
   
    playStepSoundAmount=666;
   
    public AudioClip[] stepSounds;
    public AudioClip[] jumpSounds;
    public AudioClip[] landSounds;
   
    AudioSource stepSourceA,stepSourceB,jumpSource,landSource;
   
    float currentAcceleration,currentDeceleration,currentMaxForwardSpeed,currentMaxBackSpeed,currentMaxStrafeSpeed,currentRunModifier,
   
    currentSpeedZ,currentSpeedX,speedBoost,
   
    rotationY,
   
    jumpPower,jumpZ,jumpX,
   
    addedJumpX,addedJumpZ,
   
    stepSoundAmount,stepVolume,
   
    camRotX,camRotY,previousCamRotX,
   
    camX,camY,camZ,camBobSpeed,
   
    n0,n1,combinedSpeeds,camSlerpAmount;
   
    int randomStepSoundIndex,lastStepIndex,randomLandSoundIndex,randomJumpSoundIndex;
   
    bool grounded,lookingAround,stepToggle,crouching,jumping;
   
    Quaternion camStartRot;
    Vector3 camTargetPosLocal,camStandTargetPos,camCrouchTargetPos;
   
    void Start ()
    {
        capsCollider=GetComponent<CapsuleCollider>();
       
        PhysicMaterial mat=new PhysicMaterial();
        mat.dynamicFriction=0;
        mat.staticFriction=1;
       
        capsCollider.material=mat;
       
        rb = GetComponent<Rigidbody>();
        rb.constraints=RigidbodyConstraints.FreezeRotation;
        rb.collisionDetectionMode=CollisionDetectionMode.ContinuousDynamic;
       
        crouchHeight=capsCollider.bounds.size.y*.66f;
        standHeight=capsCollider.bounds.size.y;
       
        camStandTargetPos=cam.localPosition;
        camCrouchTargetPos=new Vector3(camStandTargetPos.x,camStandTargetPos.y*.6f,camStandTargetPos.z);
        camTargetPosLocal=camStandTargetPos;
        camY=camTargetPosLocal.y;
        camX=camTargetPosLocal.x;
        camZ=camTargetPosLocal.z;
        camBobSpeed=(camBobX+camBobY+camBobZ)*1.1f;
       
        currentAcceleration= acceleration;
        currentDeceleration=deceleration;
        currentMaxForwardSpeed =maxForwardSpeed;
        currentMaxStrafeSpeed =maxStrafeSpeed;
        currentMaxBackSpeed= maxBackSpeed;
        currentRunModifier= runModifier;
       
        n0 = (maxStrafeSpeed+maxBackSpeed+maxForwardSpeed)/3;
        n1=n0+runModifier;
       
        stepSourceA=gameObject.AddComponent<AudioSource>();
        stepSourceB=gameObject.AddComponent<AudioSource>();
        jumpSource=gameObject.AddComponent<AudioSource>();
        landSource=gameObject.AddComponent<AudioSource>();
    }
   
    void Update()
    {
        if(Input.GetButtonDown ("ToggleCrouch"))
        {
            crouching=!crouching;
           
            if(crouching)
            {
                capsCollider.height=crouchHeight;
               
                camTargetPosLocal=camCrouchTargetPos;
               
                camX=camTargetPosLocal.x;
                camY=camTargetPosLocal.y;
                camZ=camTargetPosLocal.z;
               
                currentAcceleration*=crouchModifier;
                currentDeceleration*=crouchModifier;
                currentMaxBackSpeed*=crouchModifier;
                currentMaxForwardSpeed*=crouchModifier;
                currentMaxStrafeSpeed*=crouchModifier;
                currentRunModifier*=crouchModifier;
            }
            else
            {
                capsCollider.height=standHeight;
               
                camTargetPosLocal=camStandTargetPos;
               
                camX=camTargetPosLocal.x;
                camY=camTargetPosLocal.y;
                camZ=camTargetPosLocal.z;
               
                currentAcceleration=acceleration;
                currentDeceleration=deceleration;
                currentMaxBackSpeed=maxBackSpeed;
                currentMaxForwardSpeed=maxForwardSpeed;
                currentMaxStrafeSpeed=maxStrafeSpeed;
                currentRunModifier=runModifier;
            }
        }
       
        if(!lookingAround)
        {
            if(invertY)
            {
                camRotX += Input.GetAxisRaw ("Mouse Y")*rotSpeed;
            }
            else
            {
                camRotX -= Input.GetAxisRaw ("Mouse Y")*rotSpeed;
            }
           
            camRotX = Mathf.Clamp (camRotX, minRotX,maxRotX);
           
            cam.localRotation=Quaternion.Euler (camRotX,0,0);
           
            if(Input.GetButtonDown ("LookAround"))
            {
                previousCamRotX=camRotX;
                lookingAround=true;
               
                cam.localPosition=camTargetPosLocal;
            }
        }
        else
        {
            if(Input.GetButtonUp ("LookAround"))
            {
                camStartRot = cam.localRotation;
                StartCoroutine ("ReturnCamRot");
            }
            camRotY+=Input.GetAxisRaw ("Mouse X")*rotSpeed;
            camRotY = Mathf.Clamp (camRotY,minRotY,maxRotY);
           
            if(invertY)
            {
                camRotX += Input.GetAxisRaw ("Mouse Y")*rotSpeed;
            }
            else
            {
                camRotX -= Input.GetAxisRaw ("Mouse Y")*rotSpeed;
            }
           
            camRotX = Mathf.Clamp (camRotX, minRotX,maxRotX);
           
            cam.localRotation=Quaternion.Euler (camRotX,camRotY,0);
        }
       
        if(Input.GetButton ("Jump"))
        {
            jumpPower+=currentAcceleration;
           
            if(Input.GetButton ("Forward"))
                jumpZ+=currentAcceleration;
            if(Input.GetButton ("Back"))
                jumpZ-=currentAcceleration;
            if(Input.GetButton ("Left"))
                jumpX-=currentAcceleration;
            if(Input.GetButton ("Right"))
                jumpX+=currentAcceleration;
        }
       
        if(Input.GetButtonUp ("Forward"))
            if(!Input.GetButton ("Back"))
                StartCoroutine ("SlowDownZ");
        if(Input.GetButtonUp ("Back"))
            if(!Input.GetButton ("Forward"))
                StartCoroutine ("SlowDownZ");
       
        if(Input.GetButtonUp ("Left"))
            if(!Input.GetButton ("Right"))
                StartCoroutine ("SlowDownX");
        if(Input.GetButtonUp ("Right"))
            if(!Input.GetButton ("Left"))
                StartCoroutine ("SlowDownX");
       
        if(Input.GetButtonUp ("Jump"))
        {
            if(grounded)
            {
                jumpZ = Mathf.Clamp (jumpZ,-maxJumpPower,maxJumpPower);
                jumpX = Mathf.Clamp (jumpX,-maxJumpPower,maxJumpPower);
               
                addedJumpX = jumpX + currentSpeedX;
                addedJumpZ = jumpZ + currentSpeedZ;
               
                jumpPower = Mathf.Clamp (jumpPower,minJumpPower,maxJumpPower);
               
                rb.AddRelativeForce (addedJumpX*jumpMultiplierX, jumpPower*jumpMultiplierY,addedJumpZ*jumpMultiplierZ,ForceMode.Impulse);
               
                if(jumpSounds.Length>0)
                {
                    randomJumpSoundIndex=Random.Range (0,jumpSounds.Length);
                   
                    jumpSource.clip=jumpSounds[randomJumpSoundIndex];
                    jumpSource.volume=Random.Range (.5f,1f);
                    jumpSource.Play ();
                }
               
                stepSoundAmount=0;
                StopCoroutine ("SlowDownX");
                StopCoroutine ("SlowDownZ");
                currentSpeedZ=0;
                currentSpeedX=0;
               
                jumping=true;
            }
            jumpPower = 0;
            jumpX = 0;
            jumpZ = 0;
        }
       
        if(grounded)
        {
            rotationY=Input.GetAxis ("Mouse X");
           
            if(Input.GetButtonDown ("Forward") || Input.GetButtonDown ("Back"))
            {
                StopCoroutine ("SlowDownZ");
            }
            if(Input.GetButtonDown ("Left") || Input.GetButtonDown ("Right"))
            {
                StopCoroutine ("SlowDownX");
            }
           
            if(Input.GetButton ("Forward"))
            {
                currentSpeedZ+=currentAcceleration;
            }
            if(Input.GetButton ("Back"))
            {
                currentSpeedZ-=currentAcceleration;
            }
            if(Input.GetButton ("Left"))
            {
                currentSpeedX-=currentAcceleration;
            }
            if(Input.GetButton ("Right"))
            {
                currentSpeedX+=currentAcceleration;
            }
           
            if(Input.GetButton ("Run"))
            {
                speedBoost+=currentAcceleration;
            }
            else
            {
                speedBoost-=currentDeceleration;
            }
           
            speedBoost = Mathf.Clamp (speedBoost,0,runModifier);
           
            currentSpeedZ = Mathf.Clamp (currentSpeedZ,-currentMaxBackSpeed-speedBoost,currentMaxForwardSpeed+speedBoost);
            currentSpeedX = Mathf.Clamp (currentSpeedX,-currentMaxStrafeSpeed-speedBoost,currentMaxStrafeSpeed+speedBoost);
        }
    }
   
    IEnumerator SlowDownZ()
    {
        while(true)
        {
            currentSpeedZ+=currentSpeedZ>0 ? -deceleration:deceleration;
           
            if(Mathf.Abs (currentSpeedZ)<=deceleration)
            {
                currentSpeedZ=0;
                yield break;
            }
            else
            {
                yield return null;
            }
        }
    }
    IEnumerator SlowDownX()
    {
        while(true)
        {
            currentSpeedX+=currentSpeedX>0 ? -deceleration:deceleration;
           
            if(Mathf.Abs (currentSpeedX)<=deceleration)
            {
                currentSpeedX=0;
                yield break;
            }
            else
            {
                yield return null;
            }
        }
    }
   
    IEnumerator ReturnCamRot()
    {
        while(true)
        {
            camSlerpAmount+=camReturnSpeed;
            cam.localRotation =  Quaternion.Slerp (camStartRot,Quaternion.Euler (previousCamRotX,0,0),camSlerpAmount);
           
            if(camSlerpAmount>.99f)
            {
                camSlerpAmount = 0;
                camRotY = 0;
                camRotX=previousCamRotX;
                cam.localRotation = Quaternion.Euler (camRotX,0,0);
               
                cam.localPosition=camTargetPosLocal;
                camY=camTargetPosLocal.y;
                camX=camTargetPosLocal.x;
                camZ=camTargetPosLocal.z;
               
                lookingAround=false;
               
                yield break;
            }
           
            yield return null;
        }
    }
   
    Quaternion deltaRotation;
   
    void FixedUpdate()
    {
        GroundCheck();
       
        if(grounded)
        {
            rb.AddRelativeForce (currentSpeedX*speedMultiplierX,0,currentSpeedZ*speedMultiplierZ);
           
            if(!lookingAround)
            {
                deltaRotation = Quaternion.Euler(new Vector3(0,rotationY*rotSpeed,0));
                transform.rotation=transform.rotation*deltaRotation;
            }
           
            if(currentSpeedX==0&&currentSpeedZ==0)
            {
                cam.localPosition=Vector3.MoveTowards (cam.localPosition,camTargetPosLocal,camBobSpeed);
            }
           
            combinedSpeeds=Mathf.Abs (currentSpeedZ) + Mathf.Abs (currentSpeedX);
           
            if(currentSpeedX != 0 && currentSpeedZ != 0)
            {
                stepSoundAmount+=combinedSpeeds*.5f*
                    Mathf.Clamp ( Mathf.Abs (transform.InverseTransformDirection (rb.velocity).z)+
                                 Mathf.Abs (transform.InverseTransformDirection (rb.velocity).x),0,1) ;
            }
            else
            {
                stepSoundAmount+=combinedSpeeds*
                    Mathf.Clamp ( Mathf.Abs (transform.InverseTransformDirection (rb.velocity).z)+
                                 Mathf.Abs (transform.InverseTransformDirection (rb.velocity).x),0,1) ;
            }
           
            if(!lookingAround)
            {
                if(stepSoundAmount>playStepSoundAmount*.5f)
                {
                    camY-=camBobY;
                    camZ+=camBobZ;
                   
                    camX += stepToggle ? -camBobX : camBobX;
                   
                    cam.localPosition=Vector3.MoveTowards (cam.localPosition,new Vector3(camX,camY,camZ),camBobSpeed*
                                                           Mathf.Clamp ( Mathf.Abs (transform.InverseTransformDirection (rb.velocity).z)+
                                 Mathf.Abs (transform.InverseTransformDirection (rb.velocity).x),0,1));
                }
                else if(stepSoundAmount>playStepSoundAmount*.2f)
                {
                    cam.localPosition=Vector3.MoveTowards (cam.localPosition,camTargetPosLocal,camBobSpeed*1.45f);
                }
            }
           
            if(stepSoundAmount>playStepSoundAmount)
            {
                stepToggle=!stepToggle;
               
                camY=camTargetPosLocal.y;
                camX=camTargetPosLocal.x;
                camZ=camTargetPosLocal.z;
               
                if(stepSounds.Length>0)
                {
                    if(stepSounds.Length>1)
                    {
                        for(int i=0;i<Mathf.Infinity;i++)
                        {
                            randomStepSoundIndex=Random.Range (0,stepSounds.Length);
                           
                            if(randomStepSoundIndex!=lastStepIndex)
                                break;
                        }
                    }
                   
                    if(currentSpeedX != 0 && currentSpeedZ != 0)
                    {
                        stepVolume = ((float)Mathf.Abs (currentSpeedX)/n1+(float)Mathf.Abs (currentSpeedZ)/n1)*.5f;
                    }
                    else
                    {
                        stepVolume = ((float)Mathf.Abs (currentSpeedX)/n1+(float)Mathf.Abs (currentSpeedZ)/n1);
                    }
                   
                    stepVolume=Mathf.Clamp (stepVolume,0,1);
                   
                    if(stepToggle)
                    {
                        stepSourceA.clip=stepSounds[randomStepSoundIndex];
                        stepSourceA.volume=stepVolume;
                        stepSourceA.Play ();
                    }
                    else
                    {
                        stepSourceB.clip=stepSounds[randomStepSoundIndex];
                        stepSourceB.volume=stepVolume;
                        stepSourceB.Play ();
                    }
                   
                    lastStepIndex=randomStepSoundIndex;
                }
               
                stepSoundAmount=0;
            }
           
        }
       
        StickToGroundHelper ();
    }
   
    RaycastHit hitInfo;
   
    bool previouslyGrounded;
   
    void GroundCheck()
    {
        if (Physics.SphereCast(transform.position, capsCollider.radius-.01f, Vector3.down, out hitInfo,
                               ((capsCollider.height/2f) - capsCollider.radius) + groundCheckDistance))
        {
            rb.drag=rigidbodyDrag;
           
            grounded = true;
           
            if(!previouslyGrounded&&jumping)
            {
                if(landSounds.Length>0)
                {
                    if(!landSource.isPlaying)
                    {
                        randomLandSoundIndex=Random.Range (0,landSounds.Length);
                       
                        landSource.clip=landSounds[randomLandSoundIndex];
                        landSource.volume=Random.Range (.5f,1f);
                        landSource.Play ();
                    }
                }
               
                jumping=false;
            }
        }
        else
        {
            rb.drag=0;
           
            grounded = false;
        }
       
        previouslyGrounded=grounded;
    }
   
    void StickToGroundHelper()
    {
        if (Physics.SphereCast(transform.position, capsCollider.radius-.01f, Vector3.down, out hitInfo,
                               ((capsCollider.height/2f) - capsCollider.radius) +
                               stickToGroundHelperDistance))
        {
            if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
            {
                rb.velocity = Vector3.ProjectOnPlane(rb.velocity, hitInfo.normal);
            }
        }
    }
}

revised it quite a bit

How about a description as to what this is, how it works, why you posted it here (and edited it 6 months later).

What’s up?

1 Like

it’s a rigidbody first person controller that i left here in case someone finds a use for it