- Home /
Gravity with Character Controller?
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.
googling that comes up with this page. Please answer the question ins$$anonymous$$d of trying to be smart. If you have nothing to add please just move on.
The answer on the first link : The Character$$anonymous$$otor 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 ?
Transform.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.
Thanks, 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.
Answer by aldonaletto · Oct 19, 2012 at 01:27 AM
The 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.
Time.deltaTime is the time elapsed since last frame. As a rule of thumb, anything expressed in something per second should be multiplied by Time.deltaTime to become independent of the frame rate (which varies a lot!). In the case above, Rotate should rotate the character at a fixed speed in degrees per second - thus the actual angle to be rotated must be multiplied by Time.deltaTime. The same applies to the $$anonymous$$ove speed, since it's expressed in meters per second (or miles, yards, feet etc.). It's different in the Simple$$anonymous$$ove case because this method expects the moving velocity itself, and the multiplication is done internally.
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.$$anonymous$$ove (grav Time.deltaTime); } else { grav.y = 0; }
The variable speed defines the horizontal velocity - just modify it to get different velocities.
CharacterController.$$anonymous$$ove sets isGrounded to false, so I used Raycast to check the distance to ground.
Answer by Loius · Oct 19, 2012 at 12:24 AM
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;
That is basically what I had. So character.move would be a good method?
You must use $$anonymous$$ove (or Simple$$anonymous$$ove) to move the CharacterController. Translate ignores collisions, and should not be used with a CharacterController. You may ins$$anonymous$$d use Simple$$anonymous$$ove: it automatically applies gravity, but you're not allowed to modify the vertical movement - thus use $$anonymous$$ove if you plan to jump or fly.
Actually, you're considering gravity as a constant speed, not an acceleration. Thus it will fall at a constant speed, ins$$anonymous$$d 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.$$anonymous$$ove( Vector3(x, y, z) );
//...
You're absolutely right, my bad. I somehow misread that line. Never$$anonymous$$d...
Answer by Nirav-Madhani · Mar 22, 2015 at 03:26 PM
THE BEST METHOD IS TO ACTIVATE CHARACTER CONTROLLER
var controller : CharacterController = GetComponent(CharacterController);
controller.SimpleMove(Vector3 .forward * 0);
AND GRAVITY WORKS
Answer by Pro-Odermonicon · May 22, 2017 at 03:19 PM
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);
}
}
I've approved this answer because someone may find the code sample helpful; however, this question is now 5+ years old and "dude" is not a helpful answer.