How can I give the player gravity with a character controller? I tried using transform.translate as well as charactercontroller.move, but they don’t seem like the best methods.
4 Answers
4The CharacterController must be moved only with Move or SimpleMove. SimpleMove applies gravity automatically, but you can’t control the vertical movement (no fly, no jump).
The parameters passed to each function are different: SimpleMove receives the desired velocity vector (Y is ignored), while Move receives the displacement since last frame.
SimpleMove can be used like this:
var speed: float = 5; // units per second
var turnSpeed: float = 90; // degrees per second
function Update(){
transform.Rotate(0, Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime, 0);
var vel: Vector3 = transform.forward * Input.GetAxis("Vertical") * speed;
var controller = GetComponent(CharacterController);
controller.SimpleMove(vel);
}
Move receives the displacement since last frame, what is simply the desired velocity multiplied by the ubiquitous Time.deltaTime - but remember to include the gravity in the vertical velocity:
var speed: float = 5; // units per second
var turnSpeed: float = 90; // degrees per second
var jumpSpeed: float = 8;
var gravity: float = 9.8;
private var vSpeed: float = 0; // current vertical velocity
function Update(){
transform.Rotate(0, Input.GetAxis("Horizontal") * turnSpeed * Time.deltaTime, 0);
var vel: Vector3 = transform.forward * Input.GetAxis("Vertical") * speed;
var controller = GetComponent(CharacterController);
if (controller.isGrounded){
vSpeed = 0; // grounded character has vSpeed = 0...
if (Input.GetKeyDown("space")){ // unless it jumps:
vSpeed = jumpSpeed;
}
}
// apply gravity acceleration to vertical speed:
vSpeed -= gravity * Time.deltaTime;
vel.y = vSpeed; // include vertical speed in vel
// convert vel to displacement and Move the character:
controller.Move(vel * Time.deltaTime);
}
Notice that vSpeed is a member variable (declared outside any function): it stores the current vertical speed, what is necessary to produce physically correct effects when jumping or falling - the vertical velocity grows downwards while in mid air due to the gravity, like in the real world.
What if I didn't want the player's velocity to increase. Could this work? var grav : Vector3; if (!player.isGrounded) { grav.y -= gravity * Time.deltaTime; player.Move (grav * Time.deltaTime); } else { grav.y = 0; }
– Coreyf716The variable speed defines the horizontal velocity - just modify it to get different velocities.
– aldonalettoCharacterController.Move sets isGrounded to false, so I used Raycast to check the distance to ground.
– Coreyf716So I’ve noticed that they jump is a little floaty this way. Much more than say a typical Mario jump. Any idea how to get this jump to be a little more strict? I added a var gravityModifier: float And modified the line as such. vSpeed -= gravityModifier * gravity * Time.deltaTime and it feels faster of course but not quite right. Thoughts?
Like, every CharacterController script tutorial already does this.
var gravity : float;
...
gravity -= 9.81 * Time.deltaTime;
controller.Move( Vector3(x, gravity, z) );
if ( controller.isGrounded ) gravity = 0;
You must use Move (or SimpleMove) to move the CharacterController. Translate ignores collisions, and should not be used with a CharacterController. You may instead use SimpleMove: it automatically applies gravity, but you're not allowed to modify the vertical movement - thus use Move if you plan to jump or fly.
– aldonalettoActually, you're considering gravity as a constant speed, not an acceleration. Thus it will fall at a constant speed, instead of falling faster each time. A good approach is to increase the vertical speed by a (linearly interpolated) gravity acceleration each frame //... y -= gravity * Time.deltaTime; controller.Move( Vector3(x, y, z) ); //...
THE BEST METHOD IS TO ACTIVATE CHARACTER CONTROLLER
var controller : CharacterController = GetComponent(CharacterController);
controller.SimpleMove(Vector3 .forward * 0);
AND GRAVITY WORKS
Dude.
public CharacterController cc;
float vv;
float g = 14.0f;
float jf = 10.0f;
float s = 8.0f;
void Start () {
if (gameObject.GetComponent<CharacterController> () != null) {
cc = GetComponent<CharacterController> ();
} else {
gameObject.AddComponent<CharacterController> ();
cc = GetComponent<CharacterController> ();
};
}
void Update () {
cc.enabled = true;
if (Input.GetKey (KeyCode.Z)) {
s = 16.0f;
} else {
s = 8.0f;
};
if (cc.isGrounded) {
vv = -g * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.X)) {
vv = jf;
};
} else {
vv -= g * Time.deltaTime;
};
Vector3 mv = new Vector3 (Input.GetAxis("Horizontal")*s,0,Input.GetAxis("Vertical")*s);
cc.Move (mv * Time.deltaTime);
}
}
http://www.lmgtfy.com/?q=Unity+Gravity+with+Character+Controller
– AlucardJayThe answer on the first link : The CharacterMotor script does this stuff, including gravity. The answer on the second link is by Aldo, and if he said I could breathe underwater, then I would believe it! You havn't given enough detail as to your Character Controller setup (what components/scripts have you tried), and from what you have tried you have no explanation for the statement but they both seem like bad methods , what does this mean / what have you read ?
– AlucardJayTransform.translate doesn't even work. The player does not process that it is grounded on game start, so the player just falls right through the floor.
– Coreyf716@alucardj your lmgtfy throws me this page out ;)
– sdgdThanks, that comment was posted 11 months ago ;) Aldo has given a great answer that should help future users. If not, the search should yield other results.
– AlucardJay