In-Air Controls Character Controller

Does anyone know how to add air controls to this script? I know it may be a lot, but I don’t think it’s that confusing. Any help would be grateful! :slight_smile:

This is the custom controller for a third person 3D platformer:

/*PLAYER SETUP:
	For moving platforms, make a gameobject with a scale of (1,1,1), place the platform "model" and the 
    trigger with tag "Platform"(children) fitting the model INSIDE that gameobject, then animate/ move / 
    position the gameobject(parent).
    
    For jump pads, add a sphere collider set as Trigger and tagged with "Jump Pad" on the graphics/model,
    and add a child with a collider fitting the model.
*/
#pragma strict
#pragma implicit 
#pragma downcast
var moveSpeed : float = 18.0;
var rotateSpeed : float = 200.0;
var personalSpace : float = 4.0;
var jumpHeight : float = 15.0;
var gravity : float = 30.0;
var doubleHeight : float = 4.0;
var padHeight : float = 25.0;
var ladderSpeed : float = 10.0;
//-----------------------------------------------------------------------------------------------------
private var rate : float = 0.7;
private var moveDirection : Vector3 = Vector3.zero;
private var controller : CharacterController;
private var canJump = true;
private var canDoubleJump = true;
private var rotation : Vector3;
private var cooldown = false;

var walkSound : AudioClip;
var runSound : AudioClip;
var jumpSound : AudioClip;
var flipSound : AudioClip;
var landSound : AudioClip;
var SwingISound : AudioClip;
var SwingIISound : AudioClip;

var IdleAni : AnimationClip;
var WalkAni : AnimationClip;
var RunAni : AnimationClip;
var JumpAni : AnimationClip;
var DoubleJumpAni : AnimationClip;
var ClimbUpAni : AnimationClip;
var AttackAni : AnimationClip;
var AttackComboAni : AnimationClip;
var ThirdAttackAni : AnimationClip;
//"Idle"
//"Walk"
//"Run"
//"Jump"
//"DoubleJump"
//"Climb Up/Down"
//"Attack"
//"AttackCombo"
//"ThirdAttack"

function Awake(){
	controller = GetComponent(CharacterController);
}

function Update() {
    if(controller.velocity.sqrMagnitude < 0.1){
    	//animation.CrossFade("IdleAni");
    }

	if(controller.isGrounded){
	    forward = Camera.main.transform.TransformDirection(Vector3.forward);
	    forward.y = 0;
	    forward = forward.normalized;
	    right = new Vector3(forward.z,0,-forward.x);
	    h = Input.GetAxis("Horizontal");
	    v = Input.GetAxis("Vertical");
	    var inputModifyFactor = (h != 0.0  v != 0.0)? .7071 : 1.0;

	    moveDirection = (h * right + v * forward);
	    moveDirection *= moveSpeed;
		canDoubleJump = true;
		
		if(Input.GetButton("Jump")  canJump){	//JUMPING INPUT
	    	Jump();
		}			
	}	
	if(!controller.isGrounded){
		if(canDoubleJump  canJump  Input.GetButtonDown("Jump")){
			DoubleJump();
		}
	}
	if(moveDirection != Vector3.zero){
		var rotation0 = transform.rotation;
		rotation0.SetLookRotation(new Vector3(moveDirection.x,0,moveDirection.z) * rotateSpeed);
		transform.localRotation = rotation0;	
	}
		//animation.CrossFade("RunAni");
		moveDirection.y -= gravity * Time.deltaTime;
		controller.Move(moveDirection * Time.deltaTime);
//--------------------------INPUT----------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
    if(Input.GetMouseButtonDown(0)  controller.isGrounded  !cooldown){
    	AttackI();
    }
    if(Input.GetMouseButtonDown(1)  controller.isGrounded  cooldown){
    	AttackII();
    }		
}
//-----------------------------ACTIONS-----------------------------------------------------------
//-----------------------------------------------------------------------------------------------

function Jump(){
	moveDirection.y = jumpHeight;
}

function DoubleJump(){
 	moveDirection.y = jumpHeight + doubleHeight;
 	canDoubleJump = false;
}

function AttackI(){
Debug.Log("Attack I");
	cooldown = true;
	//animation.CrossFade("AttackAni");
	yield WaitForSeconds(rate);
	cooldown = false;
}

function AttackII(){
Debug.Log("Attack II");
	//animation.CrossFade("AttackComboAni");
	cooldown = false;
}

//---------------------------WORLD INTERACTIONS-----------------------------------------------------
//--------------------------------------------------------------------------------------------------

function OnTriggerStay(other : Collider){	//MOVING ON MOVING PLATFORMS
    if(other.tag == "Platform"){
        this.transform.parent = other.transform.parent;
    }
}

function OnTriggerEnter(other : Collider){	//JUMPING ONTO JUMP PADS
    if(other.tag == "Jump Pad"){
        moveDirection.y = padHeight;
        //animation.CrossFade("JumpAni");
        other.animation.Play("Jump Pad");
    }
}

function OnTriggerExit(other : Collider){	//MOVING OFF MOVING PLATFORMS
    if(other.tag == "Platform"){
        this.transform.parent = null;
    }
}

//-------------------------------TOOLS--------------------------------------------------------------
//--------------------------------------------------------------------------------------------------

function OnDrawGizmosSelected(){
	Gizmos.color = Color.green;
	Gizmos.DrawWireSphere(transform.position, personalSpace);
}

@script RequireComponent(CharacterController);

Any Help? :frowning:

I forgot to make the code shorter, a lot of it is unnecessary…

var moveSpeed : float = 18.0;
var rotateSpeed : float = 200.0;
var jumpHeight : float = 15.0;
var gravity : float = 30.0;
private var moveDirection : Vector3 = Vector3.zero;
private var controller : CharacterController;
private var canJump = true;
private var canDoubleJump = true;
function Awake(){
	controller = GetComponent(CharacterController);
}

function Update() {
    if(controller.velocity.sqrMagnitude < 0.1){
    	//animation.CrossFade("IdleAni");
    }

	if(controller.isGrounded){
	    forward = Camera.main.transform.TransformDirection(Vector3.forward);
	    forward.y = 0;
	    forward = forward.normalized;
	    right = new Vector3(forward.z,0,-forward.x);
	    h = Input.GetAxis("Horizontal");
	    v = Input.GetAxis("Vertical");
	    var inputModifyFactor = (h != 0.0  v != 0.0)? .7071 : 1.0;

	    moveDirection = (h * right + v * forward);
	    moveDirection *= moveSpeed;
		canDoubleJump = true;
		
		if(Input.GetButton("Jump")  canJump){	//JUMPING INPUT
	    	Jump();
		}			
	}	
	if(!controller.isGrounded){
		if(canDoubleJump  canJump  Input.GetButtonDown("Jump")){
			DoubleJump();
		}
	}
	if(moveDirection != Vector3.zero){
		var rotation0 = transform.rotation;
		rotation0.SetLookRotation(new Vector3(moveDirection.x,0,moveDirection.z) * rotateSpeed);
		transform.localRotation = rotation0;	
	}
		//animation.CrossFade("RunAni");
		moveDirection.y -= gravity * Time.deltaTime;
		controller.Move(moveDirection * Time.deltaTime);
}

function Jump(){
	moveDirection.y = jumpHeight;
}

function DoubleJump(){
 	moveDirection.y = jumpHeight + doubleHeight;
 	canDoubleJump = false;
}

add this to the other in the if:

 if(!controller.isGrounded){
    h = Input.GetAxis("Horizontal");
   moveDirection = (h * right + v * forward);

   moveDirection *= moveSpeed;

}

You may want to add an airSpeed variable and replace moveSpeed with that because moveSpeed might be too fast.

That didn’t quite work. It turned out just like anything else I try with it. When I press the Jump button, the player seems pretty resistant to jumping; he only get’s like an inch off the ground instead of feet, then slowly floats down.

You probably want to put a delay in for the jump with an isJumping variable.

function Jump(){

    moveDirection.y = jumpHeight;
   isJumping = true;
   yield WaitForSeconds (1);
  isJumping = false;


//then add an and in the if statement:
if(!controller.isGrounded  !isJumping)

}

also take out the “v” in the moveDirection statement:
moveDirection = (h * right * forward);
You also need the things about forward repeated in there like in the other if statement.
You might not need the delay if you do those things.

I understand where you’re going, but it’s just the floaty part. The player keeps slowly floating down, even after 1 second! Is it a problem with my gravity or something?

Your gravity is just being controlled by subtracting from the y. That’s why
forward.y = 0 has to be in that if condition. It is probably changing the y value. If that doesn’t do it, add
moveDirection.y -= gravity * Time.deltaTime;
You shouldn’t have to do that though, because gravity will be added at the end already. You should just need all the forward and right variables that are in the other if condition.

Yeah, that’s not working either. Maybe I’m doing it wrong. Here’s what mine looks like:

var moveSpeed : float = 18.0;
private var canJump = true;
private var canDoubleJump = true;
private var isJumping = false;
function Update(){
	if(!controller.isGrounded){
		if(canDoubleJump  canJump  Input.GetButtonDown("Jump")){
			DoubleJump();
		}
		if(!isJumping){
			forward.y = 0;
			h = Input.GetAxis("Horizontal");
			moveDirection = (h * right + v * forward);
			moveDirection *= moveSpeed;	
			moveDirection.y -= gravity * Time.deltaTime;
		}
	}
}

Here’s some jumping:

function Jump(){
	moveDirection.y = jumpHeight;
    isJumping = true;
    yield WaitForSeconds (1);
    isJumping = false;
}

function DoubleJump(){
 	moveDirection.y = jumpHeight + doubleHeight;
 	canDoubleJump = false;
}
        if(!isJumping){

        forward = Camera.main.transform.TransformDirection(Vector3.forward);

        forward.y = 0;

        forward = forward.normalized;

        right = new Vector3(forward.z,0,-forward.x);

            h = Input.GetAxis("Horizontal");

            moveDirection = (h * right);

            moveDirection *= moveSpeed; 


        }

It’s closer than I have ever gotten. I added v = Input.GetAxis(“Vertical”); under h to be able to use up/down keys or W/S. The only problem is the slow falling part.

You need this line after input, I didn’t notice it, it’s in the first function.
var inputModifyFactor = (h != 0.0 v != 0.0)? .7071 : 1.0;

If you do the same thing as the first " if", you should get the same results. The gravity is added at the bottom near controller.move.

There’s already a var for that in the grounded section of the script. Besides, that’s just for making sure the player doesn’t speed up when two directional buttons are pressed, and I didn’t even apply it as a matter of fact…

OK, well, because the player was grounded, you didn’t see the effects of the gravity during that input phase, which means you will need to add extra gravity in the if clause. 4
var extraGravity = something;
moveDirection.y -= extraGravity * Time.deltaTime;

You may have to isolate when getting input in air and when he’s just falling without input and treat them differently if they aren’t the same.

Ok. I’ll have to put this together another time to get all this straight, then come back with whatever I have.
Thanx!