x


How to keep CharacterController grounded without constantly applying gravity?

Ok, this is seemingly an extremely simple question. Whenever I apply Y movement (gravity) to a charactercontroller, the expected behavior happens and the object falls down until it hits the ground. The issue is when I stop applying gravity, the CharacterController constantly fluctuates between isGrounded = false and isGroudned = true. I've stripped down literally everything except for a few lines of code to test with:

 void Update
{
            Debug.Log( "is grounded: " + controller.isGrounded );
            moveDirection.y -= gravity * Time.deltaTime;
            controller.Move( moveDirection * Time.deltaTime );
}

In the code above, once the charactercontroller falls to the ground, isGrounded keeps returning true as expected. When I try this code...

        Debug.Log( "is grounded: " + controller.isGrounded );
        if( !controller.isGrounded ) 
        {
            moveDirection.y -= gravity * Time.deltaTime;
            if( moveDirection.y < -maxFallSpeed ) moveDirection.y = -maxFallSpeed;
        }
        else moveDirection.y = 0;
        controller.Move( moveDirection * Time.deltaTime );

...the controller fluctuates isGrounded values every few frames.

How do I keep the controller grounded without having to constantly apply gravity? Once it's grounded, shouldn't it stay grounded until I apply movement in the opposite direction? Thanks.

more ▼

asked Oct 16, 2012 at 04:32 AM

helios gravatar image

helios
170 48 45 47

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

I suspect that isGrounded is set by collisions in the bottom side of the CharacterController. If you wait the CC (CharacterController) to become grounded, then remove the gravity and move it horizontally, isGrounded becomes false. In your code, gravity is applied as a downwards velocity whenever the isGrounded is false; when it becomes true, you cancel the vertical velocity, what makes isGrounded turn to false - gravity is applied again, isGrounded becomes true, gravity is suspended, and so on, creating a loop that flips isGrounded true/false continuously.
Why do you want to suspend gravity? Usually, the gravity is continuously applied in order to keep the CC grounded, and there's nothing wrong with this.

more ▼

answered Oct 16, 2012 at 12:42 PM

aldonaletto gravatar image

aldonaletto
57.1k 31 79 292

I guess I just don't understand that in the above code, if the only way for gravity to be suspended is if it is grounded, how is it ever becoming ungrounded without every applying an upward force?

I'm trying to suspend gravity because of issues related to the charactercontroller and moving platforms (this is a 2d game). It falls through a vertically moving platform if no horizontal movement is applied to the CC and I suspect the constant gravity coupled with the upwards movement of the platform is causing an issue sometimes.

Oct 16, 2012 at 01:14 PM helios

This CC - moving platform issue is classic, and the usual solution is to make sure that at least one non-null Move instruction is executed every frame. The simplest (and nastiest) hack is to just include an almost null Move in Update, independently of your current movement code:

void Update(){
  controller.Move(Vector3.forward * 0.001f);
  // rest of your code
}

This looks terrible, but works fine. You can call Move again at the end of the movement code - the displacements are added, and there are no bad collateral effects.
A slightly less ridiculous solution could be to add a little displacement to X or Z in moveDirection right before doing the current Move, so that it would always be non-null:

  moveDirection.z += 0.01f;
  controller.Move(moveDirection * Time.deltaTime);
Oct 16, 2012 at 03:31 PM aldonaletto

Ah! I have no idea why this never occurred to me.. I'm just adding a very very slight displacement right before the main Move and all my troubles are gone. Thank you!

Oct 16, 2012 at 11:17 PM helios

I've actually realized that this still fails if the platform is moving fast enough vertically and the character is falling down at the same time. Is there anything that can be done in situations like this? Thanks!

Nov 13, 2012 at 12:37 AM helios

I encountered this and had a slightly different solve in my own code - instead of displacing in the X or Z directions I actually apply a very small amount of downward push (basically, instead of no gravity I add -0.1*Time.deltaTime gravity - very small). Seems to work perfectly fine for me.

Mar 07, 2013 at 05:12 AM PhobicGunner
(comments are locked)
10|3000 characters needed characters left

What if it collides with the ground when you apply downward force? Won't it bounce up in the air?

more ▼

answered Oct 16, 2012 at 06:06 AM

andisopany gravatar image

andisopany
16 2

Should it if there is no physics material?

Oct 16, 2012 at 11:15 AM helios

A CharacterController isn't under physics control, thus it doesn't react to collisions like rigidbodies - nor accept forces or have physics material.

Oct 16, 2012 at 12:21 PM aldonaletto
(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:

x776
x77
x1

asked: Oct 16, 2012 at 04:32 AM

Seen: 4518 times

Last Updated: Mar 07, 2013 at 02:14 PM