- Home /
Character Controller Not Allowing Gravity
I've added a character controller to a capsule and even though it has a rigidbody attached, it won't use gravity and fall to the floor. As soon as I disable it though, it does. I even tried making artificial gravity through scripting (the script uses flags to detect whether or not the player is touching the floor):
Vector3 moveDir = Vector3.zero;
void Update () {
moveDir.y -= gravity * Time.deltaTime;
var flags = controller.Move(moveDir * Time.deltaTime);
grounded = ((flags & CollisionFlags.CollidedBelow) != 0);
}
('controller' being the CharacterController)
That didn't even work. Why is this happening?
Edit
Here's the whole movement script:
public float speed = 10;
public float rotationSpeed = 2;
private bool canRun = true;
public float runSpeed = 15;
public bool running;
private bool canCrawl = true;
public float crawlSpeed = 5;
public bool crawling;
public float standUpTime = 3;
public float crawlHeight;
private float normalHeight;
private Vector3 tempCent;
private bool canJump = true;
public float jumpHeight = 5;
public bool jumping;
public float gravity = 1;
private Vector3 moveDir;
private Vector3 rotDir;
private float moveHor;
private CharacterController controller;
private PlayerStats playerStats;
private Transform player;
void Awake () {
player = transform;
controller = player.GetComponent<CharacterController>();
playerStats = player.GetComponent<PlayerStats>();
normalHeight = controller.height;
tempCent.y = controller.center.y/2;
}
void Update () {
bool isControllable = playerStats.isControllable;
moveDir.y -= gravity * Time.deltaTime;
if(!isControllable){
Input.ResetInputAxes();
}else{
if(controller.isGrounded){
moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDir = player.TransformDirection(moveDir);
moveDir *= speed;
moveHor = Input.GetAxis("Horizontal");
if(!crawling && !jumping){
canRun = playerStats.canRun;
running = playerStats.canRun;
}
canJump = playerStats.energy > 0;
if(moveHor > 0){
rotDir = new Vector3(0, 1, 0);
}else if(moveHor < 0){
rotDir = new Vector3(0, -1, 0);
}else{
rotDir = new Vector3(0, 0, 0);
}
if(Input.GetButton("Jump")){
if(canJump){
moveDir.y = jumpHeight;
canRun = false;
canCrawl = false;
controller.height = normalHeight;
controller.center = tempCent;
}
}
if(Input.GetKey(KeyCode.LeftShift)){
if(canRun){
moveDir *= runSpeed;
canCrawl = false;
running = true;
}
if(crawling){
animation.Play("GetUp");
canRun = true;
crawling = false;
controller.height = normalHeight;
controller.center = tempCent;
}
}else{
running = false;
}
if(Input.GetKey("c")){
if(canCrawl){
moveDir *= crawlSpeed;
controller.height = crawlHeight;
tempCent.y -= 0.25F;
controller.center = tempCent;
canRun = false;
canJump = false;
crawling = true;
}
}else{
crawling = false;
}
controller.Move(moveDir * Time.deltaTime);
controller.transform.Rotate(rotDir * Time.deltaTime, rotationSpeed);
}
moveDir.y -= gravity * Time.deltaTime;
}
}
}
If it works with the Controller disabled, do you have another collider on it(I mean other than the character Controller)
It is possible that the character controller is detecting that and thinks it is on the ground.
Side note, you know of Simple$$anonymous$$ove, yes?
No other colliders. And no I am not familiar with Simple$$anonymous$$ove.
Oh and also, it doesn't think that it is on the ground. "grounded" equals false.
Answer by aldonaletto · Jul 15, 2012 at 02:41 AM
You can't mix Rigidbody and CharacterController in the same object - the object becomes crazy! You must use only one of them. The CharacterController is easier: it already has a isGrounded property, and you can start with one of the example scripts in SimpleMove (rotates with AD, moves with WS, has automatic gravity but can't jump or fly) or Move (moves with WASD, can jump, gravity is added by script) and modify it to suit your needs.
The Rigidbody is too wild, but can be controlled in a SimpleMove fashion with a simple script like this:
var speed : float = 3.0; var rotateSpeed : float = 3.0;
function Start(){ rigidbody.freezeRotation = true; }
function Update () { // Rotate around y - axis transform.Rotate(0, Input.GetAxis ("Horizontal") rotateSpeed, 0); // Calculate forward/backward velocity: var moveVel = transform.forward speed * Input.GetAxis ("Vertical"); moveVel.y = rigidbody.velocity.y; // but conserve gravity effect rigidbody.velocity = moveVel; }
Okay I've changed it to use controller.$$anonymous$$ove() and if(controller.isGrounded) but the character controller still doesn't fall. Not even with this code:
moveDir.y -= gravity * Time.deltaTime;
I even put that as the first thing in the Update void and it won't change.
That's weird - this script should work. Have you removed the rigidbody? Another thing: the CharacterController has some problems with childed colliders that touch the capsule - it "thinks" to be colliding with its own children, and may get stuck or move to weird directions.
If nothing works, I suggest you to start anew: create an empty object, add the CharacterController and your script to it - this must work!
Nope! That didn't work either. And there was no rigidbody or other colliders on the original object. This is very strange. I'm going to post the whole movement script in my question.
You're a victim of bad indentation: controller.$$anonymous$$ove is inside the if (controller.isGrounded) branch, where moveDir.y is always zeroed. By the way, the Rotate instruction is wrong too. Change these lines:
... controller.$$anonymous$$ove(moveDir * Time.deltaTime); //<- move this line... controller.transform.Rotate(rotDir * Time.deltaTime, rotationSpeed); // this instruction is wrong! } moveDir.y -= gravity * Time.deltaTime; } }to this:
... // modify the Rotate instruction to this: controller.transform.Rotate(rotDir * Time.deltaTime * rotationSpeed); } moveDir.y -= gravity * Time.deltaTime; controller.$$anonymous$$ove(moveDir * Time.deltaTime); //<- to this position } }Always indent your scripts with a tab or two spaces per indentation level - it's impossible to avoid mistakes without proper indentation!
Answer by Avaista · Jul 15, 2012 at 11:22 PM
moveDir.y -= gravity * Time.deltaTime;
if(!isControllable)
{
Input.ResetInputAxes();
}
else
{
if(controller.isGrounded)
{
moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Perhaps try applying gravity after you set the moveDirection.
Tried it after and before and everything in between. $$anonymous$$aybe something in the code is stopping it, although I have found nothing.
Semi stupid question but I must ask. Is PlayerStat.controllable set to true?
Yeah, I permanently set it on true for testing to make sure.
Yes sorry, would've commented on it but I don't have access to my computer at the moment. Just a stupid question here: how do you mark more than one answer as the one that solved it? I've seen it done before.
Answer by Avaista · Jul 16, 2012 at 12:41 AM
Alright I think I got it. Lets just take out te content of that if statement and...
void Update()
{
bool isControllable = true;
moveDir.y -= gravity * Time.deltaTime;
if (!isControllable)
{
Input.ResetInputAxes();
}
else
{
if (controller.isGrounded)
{
//Omitted To Demonstrate the lol
}
moveDir.y -= gravity * Time.deltaTime;
}
}
Something be missing, lad....
I added an else and applied the movement to the Move, and it worked. Good Luck, and Have Fun!
Side note, I just noticed that when I post answers and comments I have different names 0.0
Edit: Fixed
Answer by Nirav-Madhani · Feb 28, 2015 at 08:25 AM
Its very simple. You may have noticed Gravity working every time your player moves. When character controller is triggered , gravity works. that's what we need to do without moving character!
var controller : CharacterController = GetComponent(CharacterController);
controller.SimpleMove(Vector3.forward * 0);
its JS.
Your answer
Follow this Question
Related Questions
Gravity for my AI 0 Answers
Distance between 2 objects exteriors? 1 Answer
How reliable are isGrounded checks? 1 Answer
why does character controller accelerate off ledges? 1 Answer
Rpg style movement help. 2 Answers