How To Make The FPS Character Crouch

I have put together a simple FPS game, but I just can't get my character to crouch. I've searched it up and have seen people shorten the Character Controller, but what I would like is to have the character controller shorten, and the camera as well. This way, the character can squeeze into places like vents, holes, or whatever. I've seen Controller.height = 0.5, but I also would like the camera to move down with it.

Thanks in advance :D

This is what I do, the function crouch lowers the character controller height & collider and sets crouching to true. crouchDeltaHeight is my variable for the height change when crouching. (All of this would be in the FPSWalker default script).

    function crouch() {
        this.GetComponent(BoxCollider).size -= Vector3(0,crouchDeltaHeight, 0);
        this.GetComponent(BoxCollider).center -= Vector3(0,crouchDeltaHeight/2, 0);
        crouching = true;
    }

And then in update the camera lowers to crouch height if crouching or returns to normal otherwise (it's in update to make it look smooth).

if(crouching){
    if(mainCamera.transform.localPosition.y > crouchingCamHeight){
        if(mainCamera.transform.localPosition.y - (crouchDeltaHeight*Time.deltaTime*8) < crouchingCamHeight){
            mainCamera.transform.localPosition.y = crouchingCamHeight;
        } else {
            mainCamera.transform.localPosition.y -= crouchDeltaHeight*Time.deltaTime*8;
        }
    }
} else {
    if(mainCamera.transform.localPosition.y < standardCamHeight){
        if(mainCamera.transform.localPosition.y + (crouchDeltaHeight*Time.deltaTime*8) > standardCamHeight){
            mainCamera.transform.localPosition.y = standardCamHeight;
        } else {
            mainCamera.transform.localPosition.y += crouchDeltaHeight*Time.deltaTime*8;
        }
    }

}

This is the code to stop crouching and return to normal:

        function stopCrouching(){
            crouching = false;
            this.GetComponent(BoxCollider).size += Vector3(0,crouchDeltaHeight, 0);
            this.GetComponent(BoxCollider).center += Vector3(0,crouchDeltaHeight/2, 0);
        }

And here's what I have in update to trigger it:

    if (Input.GetButtonDown ("Crouch")){
    if(crouching){
        stopCrouching();
        return;
    }

    if(!crouching)
        crouch();
}

I don't know if this is the best solution but I was thinking as long as you had the camera parented to the capsule you are using as your character you could just make an animation that scales the capsule on the y-axis.

My suggestion would be having five variables, for the hieght and camera position before and after crouching and a variable that ays if you are crouching. Have the camera position be relative, so that it is always added to the characters own position. If your weapons are a child of your camera then you will see them move down as well. This may be an issue with graphics, as if you are using a mesh for the character you will have to create an entire motion sequence seperate from the original and have them programmed individualy (Animation Programing can be a pain in FPS) and afterwards should you want a death scene the rigidbody formed would have to be altered for a 'crouch death'. Lastly you would be forced to decide how your crouching affects your jumping, whether you can jump when crouched, if so can you jump as high, and that would involve delving into the fps character made by unity (I am presuming you are using it.) which is a difficult process.

try this…
works perfectly :slight_smile:

var target : Transform;
var initial :Transform;
private var old : Transform;
var bool : boolean;
var smooth = 100.0;

function Start(){

  initial.position=transform.position;
  }

function Update () {
if(Input.GetKey("c"))
{  
   bool = true;
}
else
 bool=false;

if(bool)
{
  
  transform.position = Vector3.Lerp (transform.position,
               target.position,Time.deltaTime * smooth);
}

else 
transform.position = Vector3.Lerp (transform.position,
             initial.position,Time.deltaTime * smooth);
}

Fore anyone trying to use the FPS controller:

private var walkSpeed: float = 8;    // regular speed

private var runSpeed: float = 15;    // run speed

private var crouchSpeed: float = 3;  // crouching speed

private var speed: float;            // the current speed state



private var crouchHeight : float;     // variables for character height while crouching

private var crouchingHeight : float;  

private var standingHeight: float;    // height of character while standing

private var crouching = false;        // boolean is crouching?

private var running = false;          // boolean is running?



private var characterMotor: CharacterMotor;  //direct variable to the characterMotor

private var mainCamera: GameObject;          // direct variable to the mainCamera



function Start(){

	//initialize

    characterMotor = GetComponent(CharacterMotor);

   	mainCamera = gameObject.FindWithTag ("MainCamera");

   	standingHeight = mainCamera.transform.localPosition.y;

    crouchingHeight = (standingHeight / 2);

    crouchHeight = (standingHeight - crouchingHeight);

}



function Update(){

    

    //simple machine for setting the current speed of the character

    if( crouching ){

    	speed = crouchSpeed;

    }else if( running ){

    	speed = runSpeed;

    }else{

    	speed = walkSpeed;

    }

    

    //If the sprint button is clicked, and not crouching .. SPRINT!

    if (Input.GetKey("left shift") || Input.GetKey("right shift")){

    	if(!crouching){

	        running = true;

	        CameraZoom.sprint = true;	//sets sprint true so the camera knows to pan out

	    }

    }else {

    	CameraZoom.sprint = false;

    	running = false;

    }

  

  	// if crouch button has been pressed, put FPS into crouch

    if (Input.GetButtonDown ("Crouch")){

    	if(crouching){

        	stopCrouching();

        	return;

   	 	}

    	if(!crouching)

       		 crouch();

	}

  

    // crouch with smoothing

    if(crouching){

	    if(mainCamera.transform.localPosition.y > crouchingHeight){

	        if(mainCamera.transform.localPosition.y - (crouchHeight*Time.deltaTime*8) < crouchingHeight){

	            mainCamera.transform.localPosition.y = crouchingHeight;

	        } else {

	            mainCamera.transform.localPosition.y -= crouchHeight*Time.deltaTime*8;

	        }

	    }

		} else {

	    if(mainCamera.transform.localPosition.y < standingHeight){

	        if(mainCamera.transform.localPosition.y + (crouchHeight*Time.deltaTime*8) > standingHeight){

	            mainCamera.transform.localPosition.y = standingHeight;

	        } else {

	            mainCamera.transform.localPosition.y += crouchHeight*Time.deltaTime*8;

	        }

	   	 }

	}

	//set the max speed in the char motor;

	 characterMotor.movement.maxForwardSpeed = speed;

}



// sets teh size of the collider to crouch size

function crouch() {

        this.GetComponent(CharacterController).height -= crouchHeight;

        this.GetComponent(CharacterController).center -= Vector3(0,crouchHeight/2, 0);

        crouching = true;

 }

// resets the size of the collider to standing size  

 function stopCrouching(){

	    crouching = false;

	    this.GetComponent(CharacterController).height += crouchHeight;

	    this.GetComponent(CharacterController).center += Vector3(0,crouchHeight/2, 0);

}

I tried getting these scripts to work in unity for the fps controller, and nada. One has the CameraZoom thing, which gives an error, and the other, looks good and simple, but doesn’t do anything. I’m too brain dead right now to go into niggly details and try to figure out why these don’t work…

Am I supposed to input these scripts into the character motor script? Or as a separate script? There are no instructions on how to actually implement these scripts, where they go, etc…

https://www.dropbox.com/s/yf7glln3jb15mz4/AdvancedMotion.js

Just attach this to the PlayerController, and you’re good to go! I also made it fully configurable. (Walking speed, sprint speed, and crouch speed. As well as customizable keys for each fuction.)

I used this. You just attach it to your first person controller and you can sprint and crouch. Hope you like it.

Advanced Character Motor Add-on.js

var walkSpeed: float = 7; // regular speed
var crchSpeed: float = 3; // crouching speed
var runSpeed: float = 20; // run speed
 
private var chMotor: CharacterMotor;
private var ch: CharacterController;
private var tr: Transform;
private var height: float; // initial height
 
function Start(){
    chMotor = GetComponent(CharacterMotor);
    tr = transform;
    ch = GetComponent(CharacterController);
    height = ch.height;
}
 
function Update(){
 
    var h = height;
    var speed = walkSpeed;
 
    if (ch.isGrounded && Input.GetKey("left shift") || Input.GetKey("right shift")){
        speed = runSpeed;
    }
    if (Input.GetKey("c")){ // press C to crouch
        h = 0.5 * height;
        speed = crchSpeed; // slow down when crouching
    }
    chMotor.movement.maxForwardSpeed = speed; // set max speed
    var lastHeight = ch.height; // crouch/stand up smoothly 
    ch.height = Mathf.Lerp(ch.height, h, 5*Time.deltaTime);
    tr.position.y += (ch.height-lastHeight)/2; // fix vertical position
}