Finishing Touches On Controller

I almost done with my custom controller, been working on it for a week. UGH! But there’s just one little thing. When the player jumps, I need it to keep facing parallel with the XZ plane. For some reason, the object sort of looks up when I jump, then when falling, it looks down. How would I be able to restrict the object from looking at the y axis? This is the script I have now. I know it’s big, but you may attach it to a cube and have fun with it, and see what I’m talking about. Also, if you could give me some help on how I can do the In Air Controls, that would be great. Thanks! :slight_smile:

#pragma strict
#pragma implicit 
#pragma downcast
//OUTSIDE SCRIPT VARIABLES
var canMove = true;
var moveSpeed : float = 4.0;
var rotateSpeed : float = 200.0;
var canJump = true;
var jumpHeight : float = 12.0;
var gravity : float = 30.0;
var canDoubleJump = true;
var doubleHeight : float = 4.0;
var padHeight : float = 25.0;
private var moveDirection = Vector3.zero;

function Update(){
    var controller : CharacterController = GetComponent(CharacterController);
    //ENABLES THE MOVEMENT
    if(controller.isGrounded  canMove)
    {//(X,Y,Z)
	   // moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,Input.GetAxis("Vertical"));                             
	    //moveDirection = transform.TransformDirection(moveDirection);
	    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");
	    
	    moveDirection = (h * right + v * forward);
	    moveDirection *= moveSpeed;
	    
    	canDoubleJump = true;
    //CONTROLS JUMPING
    if(Input.GetButton ("Jump")  canJump)
    {
    	moveDirection.y = jumpHeight;
    }
 }
    //CONTROLS JUMPING IN AIR
    if(!controller.isGrounded)
    {
    
    }
    //DOUBLE JUMPING
    if(!controller.isGrounded  canDoubleJump  canJump  Input.GetButtonDown("Jump"))
    {
 		moveDirection.y = jumpHeight + doubleHeight;
 		canDoubleJump = false;
	}
	if(moveDirection != Vector3.zero)
	{//Looks at its direction
		var rotation = transform.rotation;
		rotation.SetLookRotation(moveDirection * rotateSpeed);
		transform.rotation = rotation;
	}//Applys gravity and movement
	moveDirection.y -= gravity * Time.deltaTime;
    controller.Move(moveDirection * Time.deltaTime);
}

function OnTriggerStay(other : Collider){
    //MOVING ON PLATFORMS//
    if(other.tag == "Platform")
    {
        this.transform.parent = other.transform.parent;
    }
    /*Make a gameobject with a scale of (1,1,1), place the platform model and the 
    trigger with tag "Platform"(children) INSIDE that gameobject, then animate/ move / 
    position the gameobject(parent).
    */
}

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

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

@script RequireComponent(CharacterController);

One thing which you did, which is terrible, is you declared your var for controller in update. Not bad, but what is, is the call to get its component. Get component is a costly call which should be done wisely, strategically, and sparingly. What you have done calls it, every frame. That’s a lot of frames. You only need to call it once. Cache it and move on.

Declare the var as a global to the script, and get its component is Awake or Start.

Yeah, I recently did some research and yes, getting components are costly, which is why my last game lagged so much. I believe out of the entire game, I had at least 4000 lines of code filled with get components in updates. Thanks for the tip.

Any more help with my jumping problem? How about moving in air?

Hi, do you mean you do not want the cube to rotate while in the air?

I mean I don’t want the cube to rotate on its X-axis while in the air, or Z-axis for that matter. I want it to rotate on it’s Y-axis, just like a average platform controller.

Ok. I solved my look at y-axis jumping problem by adding this.

transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")));

Instead of this:

var rotation = transform.rotation;
rotation.SetLookRotation(moveDirection * rotateSpeed);
transform.rotation = rotation;

Very greatful, but I still can’t figure what to put in the in air controls brackets. A lot of people say to remove the controller .isGrounded, but that only makes the problem worse. It sounds like it would help, but it’s one of those things you have to test out to see. Any help with that?

What is it supposed to do. While in the air? Rotate? If so, look up transform, rotate.

Scratch what I said above. It’s still crap.

Anyways, it’s simple. It’s suppose to be able to move in air like any other platformer. The script is already quite accessible, you can throw this on a cube and press play to see for yourself.

Hi again, I am not sure of the syntax in javascript but in C# I would change the following line:

rotation.SetLookRotation(moveDirection * rotateSpeed);

to something such as:

rotation.SetLookRotation(new Vector3(moveDirection.x,0,moveDirection.z)* rotateSpeed);

Regards.

In the vector, y had to be changed from 1 to 0, but it worked like a charm. Thank you kindly. :slight_smile:
EDIT: I saw you corrected it. My bad.
Only one more problem left. In air controls…

This doesn’t do it for you?

No, no. That is very basic, almost too basic. It moves, but it doesn’t turn in its direction, or move relative to the camera, or double jumps like my controller script. The only thing I need left is moving while in the air.

Almost got it. But can someone show me how to make this in air movement relative to the camera?

//IN-AIR CONTROLS
    if(!controller.isGrounded  canMove)
    {
  		moveDirection.x = Input.GetAxis("Horizontal");
  		moveDirection.x *= moveSpeed + 3;
  		moveDirection.z = Input.GetAxis("Vertical");
  		moveDirection.z *= moveSpeed + 3;
    }

I’m using this for camera relative on the ground, btw:

//ENABLES THE MOVEMENT
    if(controller.isGrounded  canMove)
    {//(X,Y,Z)
	    //moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,Input.GetAxis("Vertical"));                             
	    //moveDirection = transform.TransformDirection(moveDirection);
	    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");
	    
	    moveDirection = (h * right + v * forward);
	    moveDirection *= moveSpeed;
	    
	    canDoubleJump = true;
    //CONTROLS JUMPING
    if(Input.GetButton ("Jump")  canJump)
    {
    	moveDirection.y = jumpHeight;
    }
  }

Also, how can you check if a gameobject is moving on the Y plane? i.e:

if(!controller.isGrounded “gameobject is NOT moving along the Y plane”){
//Do something…
}

Sorry if you have already, but can you better explain what is happening, or what you want to happen? I am confused with this relative to the camera issue you have.

Without relative to camera, if you press W for instance, the player will move forward yeah? That’s only if the player is facing forward, and the camera is behind it. But if you have the camera in front, and press W, the player will look like it’s moving backwards. Go to 1:30-2:05 of this video for a visual explanation. http://vimeo.com/channels/151501/33034361#/channels/151501/33012928

If you want to see the problem I have, put this script on a cube with a sphere for a face(no variables need changing), and put a Mouse Orbit Script on a Camera called Main Camera.
#pragma strict
#pragma implicit
#pragma downcast
//OUTSIDE SCRIPT VARIABLES
var canMove = true;
var moveSpeed : float = 8.0;
var rotateSpeed : float = 200.0;
var canJump = true;
var jumpHeight : float = 12.0;
var gravity : float = 30.0;
var canDoubleJump = true;
var doubleHeight : float = 4.0;
var padHeight : float = 25.0;

private var moveDirection = Vector3.zero;
private var inAir = Vector3.zero;
private var controller : CharacterController;
private var rotation : Vector3;

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

function Update(){
//ENABLES THE MOVEMENT
if(controller.isGrounded canMove)
{//(X,Y,Z)
//moveDirection = Vector3(Input.GetAxis(“Horizontal”), 0,Input.GetAxis(“Vertical”));
//moveDirection = transform.TransformDirection(moveDirection);
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”);

moveDirection = (h * right + v * forward);
moveDirection *= moveSpeed;

canDoubleJump = true;
//CONTROLS JUMPING
if(Input.GetButton (“Jump”) canJump)
{
moveDirection.y = jumpHeight;
}
}//IN-AIR CONTROLS
if(!controller.isGrounded canMove)
{
moveDirection.x = Input.GetAxis(“Horizontal”);
moveDirection.x *= moveSpeed + 1.5;
moveDirection.z = Input.GetAxis(“Vertical”);
moveDirection.z *= moveSpeed + 1.5;
}
//DOUBLE JUMPING
if(!controller.isGrounded canDoubleJump canJump Input.GetButtonDown(“Jump”))
{
moveDirection.y = jumpHeight + doubleHeight;
canDoubleJump = false;
}
if(moveDirection != Vector3.zero)
{//Looks at its direction if it’s not facing Z forward
var rotation = transform.rotation;
rotation.SetLookRotation(new Vector3(moveDirection.x,0,moveDirection.z) * rotateSpeed);
transform.rotation = rotation;
}
if(!controller.isGrounded)
{

}
//Applys gravity and movement
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}

function OnTriggerStay(other : Collider){
//MOVING ON PLATFORMS//
if(other.tag == “Platform”)
{
this.transform.parent = other.transform.parent;
}
/*Make a gameobject with a scale of (1,1,1), place the platform model and the
trigger with tag “Platform”(children) INSIDE that gameobject, then animate/ move /
position the gameobject(parent).
*/
}

function OnTriggerEnter(other : Collider){
//JUMPING ONTO JUMP PADS
if(other.tag == “Jump Pad”)
{
moveDirection.y = padHeight;
canDoubleJump = true;
}
//Place a trigger taged “Jump Pad” on the graphics and make it a child
}

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

@script RequireComponent(CharacterController);

I can control the player relative to the camera on the ground(if you watched the vid), but not in the air. Also, when I jump, the character snaps to the front. Hopfully this will explain everything. Hope you can help! :slight_smile:

:slight_smile:

Ok,
So the issue is that you want the player to always move “away” from the camera, if pressing up.
Yes?

If so, you need to gather the camera’s direction, which way it is facing. I would do this, as as far as I know, there is no built in function to know this. I could be wrong but I digress. I would at pressing the moveForward btn, gather the cam’s direction by checking the x plane vector, y,z between the player and camera.

Once you have this vector, you tell the player to move in that direction.

Or, you could place an empty object as a child in the camera. Then, place this at 0,0,30. And lets assume you player is always at 0,0,15 relative to the camera. Then, you can easily insure the player faces that node.

That’s what I’ve been trying to figure out. I agree with the finding the camera’s forward direction. I got that part down:

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

It’s applying that direction relative to the main camera when W,S,A, or D is pressed while !controller.isGrounded(not on ground, but in the air). In the script, the grounded controls works perfectly, but not in air…I don’t see the problem with putting the same script in there. Perhaps if I call canMove to false, and make a airMove variable, and call it true?