x


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;
 }
 }
}
more ▼

asked Jul 15 '12 at 12:05 AM

Overlord gravatar image

Overlord
484 66 78 88

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 SimpleMove, yes?

Jul 15 '12 at 12:37 AM Avaista

No other colliders. And no I am not familiar with SimpleMove.

Jul 15 '12 at 01:25 AM Overlord

Oh and also, it doesn't think that it is on the ground. "grounded" equals false.

Jul 15 '12 at 02:07 AM Overlord
(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

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;
}
more ▼

answered Jul 15 '12 at 02:41 AM

aldonaletto gravatar image

aldonaletto
41.4k 16 42 196

Okay I've changed it to use controller.Move() 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.

Jul 15 '12 at 03:02 AM Overlord

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!

Jul 15 '12 at 05:33 AM aldonaletto

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.

Jul 15 '12 at 10:07 PM Overlord

You're a victim of bad indentation: controller.Move 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.Move(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.Move(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!

Jul 16 '12 at 03:14 AM aldonaletto
(comments are locked)
10|3000 characters needed characters left
 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.

more ▼

answered Jul 15 '12 at 11:22 PM

Avaista gravatar image

Avaista
484 8 23 31

Tried it after and before and everything in between. Maybe something in the code is stopping it, although I have found nothing.

Jul 15 '12 at 11:52 PM Overlord

Semi stupid question but I must ask. Is PlayerStat.controllable set to true?

Jul 16 '12 at 12:25 AM Avaista

Yeah, I permanently set it on true for testing to make sure.

Jul 16 '12 at 02:19 AM Overlord

Did you see my answer below ?

Jul 16 '12 at 02:26 AM Avaista

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.

Jul 16 '12 at 04:06 AM Overlord
(comments are locked)
10|3000 characters needed characters left

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!

more ▼

answered Jul 16 '12 at 12:41 AM

Avaista gravatar image

Avaista
484 8 23 31

Side note, I just noticed that when I post answers and comments I have different names 0.0

Edit: Fixed

Jul 16 '12 at 12:42 AM Avaista
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x670
x574
x459

asked: Jul 15 '12 at 12:05 AM

Seen: 1417 times

Last Updated: Jul 16 '12 at 04:12 AM