Proper collision detection with CharacterController?

Note: I’ve tried searching but can not find much relating to this problem.

Problem
So it seems character controllers will ONLY do collision detection if they are moving, and they will only detect in the direction they are moving.

(Character not moving, collision does not trigger, all objects pass through)

Not only that, but if any part of the object passes through the player as he’s running into it, the entire player will run right through it.

(Moving towards object, rotating object clips through player’s knee, player passes right through)

This makes interesting platforming puzzles near impossible.

Attempted Solutions

  1. I’ve tried constantly having the controller vibrating just enough to get it checking for collisions, still passes through objects easily.
  2. I’ve tried with a rigidbody in FixedUpdate, however I could not properly get it to replicate player movements with Forces (it slides all over), and using velocity seemed very buggy (slow movement, jittery on slopes, automatically slides down hills).

Can anyone help point me to a solution? Either with improving controller collisions, or how to make rigidbody behave like a human (able to run/change direction/stop quickly) without automatically sliding down slopes?

Basically I would like to have full control of movement, with collision properly working.

Thanks!

2 Likes

Probably a dumb question but are you sure there is colliders on the objects and they aren’t set to isTrigger?

1 Like

Im pretty sure I can answer that question for them, as Im having the EXACT same problem and was just about to post about it but found this first.

Yes there is a collider on the object, no its no set to isTrigger. In my case there is a Mesh Collider on the object and a character controller on the character. I have also tried the two solutions the OP tried with the same results.

My situation differs slightly, but is effectively the same. Im my case the object isnt moving, but instead the some verticies on the mesh change positions and end up ever so slightly inside the collider for the CharacterController.

The result is there is no collision resolution between the object and the character.

1 Like

Sorry, I created a solution but didn’t realize anyone had replied to this.

I just rewrote it and commented everything so it can apply to anyone. Here’s my solution:
(It essentially checks around the player for platforms, and pushes him out of them properly)

    CharacterController controller;
    float distance;
    int platLayer;

    void Start(){
        controller = GetComponent<CharacterController>();

        //Distance is slightly larger than the
        distance = controller.radius + 0.2f;

        //First add a Layer name to all platforms (I used MovingPlatform)
        //Now this script won't run on regular objects, only platforms.
        platLayer = LayerMask.NameToLayer("MovingPlatform");
    }

    public void Update(){
        RaycastHit hit;

        //Bottom of controller. Slightly above ground so it doesn't bump into slanted platforms. (Adjust to your needs)
        Vector3 p1 = transform.position + Vector3.up * 0.25f;
        //Top of controller
        Vector3 p2 = p1 + Vector3.up * player.controller.height;

        //Check around the character in a 360, 10 times (increase if more accuracy is needed)
        for(int i=0; i<360; i+= 36){
            //Check if anything with the platform layer touches this object
            if (Physics.CapsuleCast(p1, p2, 0, new Vector3(Mathf.Cos(i), 0, Mathf.Sin(i)), out hit, distance, 1<<platLayer)){
                //If the object is touched by a platform, move the object away from it
                controller.Move(hit.normal*(distance-hit.distance));
            }
        }

        //[Optional] Check the players feet and push them up if something clips through their feet.
        //(Useful for vertical moving platforms)
        if (Physics.Raycast(transform.position+Vector3.up,-Vector3.up, out hit, 1, 1<<platLayer)){
            controller.Move(Vector3.up * (1-hit.distance));
        }
    }
10 Likes

Assuming the Character Controller does its movement in FixedUpdate (I’m not positive that it does but I would think it would) then you should move the collisions checks and move to FixedUpdate as well.

That said, I’m pretty sure there a non-manual solution to this. It’s hard to say what’s wrong since it could a number of things factoring into the issue you were seeing. What colliders are on the terrain that’s moving? Are they static? How are you moving them?

Actually I just checked the documentation and found this,

“A CharacterController is not affected by forces and will only move when you call the Move funtion. It will then carry out the movement but be constrained by collisions.”

So you’ll probably have to manually move it (as you are) or create your own controller using a rigidbody. I’d still move the collision checks and adjustments to FixedUpdate :slight_smile:

1 Like

Few things I’ve found

You may be mixed up with a Rigidbody. Here’s a few things I’ve discovered with the two.

Rigidbody:

  • Done in FixedUpdate()
  • Uses Unity’s full physics system. It can be used with physics forces/impulses, etc.
  • Slides down hills however, since friction doesn’t seem to do much. It’s best suited for objects but doesn’t have much control for players.
  • Works with OnCollision events

CharacterController:

  • Done in Update()
  • Does NOT use any physics whatsoever, 100% player controlled.
  • The collider itself can not be rotated in any way. It is always vertical.
  • Collides against objects, ONLY in the direction it’s currently moving. If it is moving forward, it will NOT collide with things that hit it’s back or side. If it is not moving, it will NOT collide with anything. If it’s collider passes through an object (such as the object moving through it) it wll NO LONGER collide with that object.
  • Does not work with OnCollision events. Only works with OnControllerColliderHit() against objects it’s currently moving into. Not for anything that collides into it.

Because of that, you can see charactercontroller is great for movement, but other moving objects give it problems since it only collides into the direction it’s actively moving in.

Edit:
For your second post, CharacterController and Rigidbody don’t work together unfortunately, they go kind of crazy lol. Also, Rigidbody’s can have interpolation turned on to smooth out their movements. CharacterController won’t have interpolation. So if you were to move those into fixed Updates, it may seem jerky when objects push the player since it’s on a different update han the controller. But hey, might as well try it if you think it’ll help. :slight_smile:

15 Likes

Not mixed up with but I thought it was more integrated with the physics engine. Good information though!

Yeah, I went crazy trying to solve this stupid Controller issue and read up just about everything possible on the subject. Really is a shame it’s not more integrated with the physics engine like you mentioned. :frowning:

1 Like

@Juice-Tin

Thanks for the response.
This is similar to the idea is was pondering for my game I just hadn’t taken the time to do it because I was hoping there was a more “built in” solution to unity.

Lucky for me the way i have things setup I wont have to do a do a CapsuleCast at-least.

@cjddmut
If Juice-Tin has it set up anything like me, then he is using the CharacterController, which from all examples ive found handles its movement in update not FixedUpdate due to the fact it is not a rigidBody im guessing. I’ve often wondered why CharacterController examples uses update and not fixedUpdate, and the lack of a rigidBody is the only reason i can think of.

As far as why it is happening its because the CharacterController is LAME and just simply inadequate for most uses but ive just been way to busy with other aspects of my project to sit down and write up a proper character controller using a rigidbody.

1 Like

Ah ya beat me to it Juice, lol

Just a heads up, I’ve tried RigidBody and it WILL slide down all slopes. If you’re using terrain and have any area that isn’t perfectly flat, your character is going to slowly slide down it. So… To save more headaches just stay with your charactercontroller lol.

Ps. it’s totally lame.

1 Like

try this Custom Character Controller in Unity: Part 5 – Release 1.0.0 | Roystan Ross

Have you tried CharacterController.detectCollisions.
CharacterControllers collide when it is moving and the collider is not. But if you turn on detectCollision moving or falling objects collide with characterController

this problem is fixed with unity 5.2 i think

@Erind
Can you confirm this? Im currently have some aspects of the project ripped open making it unable to load to a state where i can test this. This would be fantastic.

@Juice-Tin did this problem get resolved in later versions of Unity?
Does the rotating Collider have a Rigidbody?
Does the problem disappear if you call Move on every fixed update, but tell it to move zero distance.

@MortenSkaaning

While im obviously not Juice-Tin i can answer some of your questions as i was having the same issue. Plus i think Juice-Tin came up with a workaround for his issue.

Does a new version of unity fix this?
Unknown, my project is getting an overhaul so i can not test this. Hoping someone else can and report back.

Does the rotating Collider have a rigidbody?
No, not normally, but it has been tried with one. The issue is with the CharacterController itself and how it handles collisions, unless this has been changed in a newer version of unity.

Does the problem disappear if you move on every fixed update, but tell it to move zero distance?
No, moving zero distance is not moving, this the CharController will detect no collision as it will only detect collision if you are moving, and in the direction you are moving in.

They have a big problem with the character controller since unity 5, we are in december … alwayse the same

Check out : Character controller problem since unity 5 - Unity Engine - Unity Discussions

In Unity 5.4 Alpha 5 we’re exposing a “recovery” mode of CharacterController. This might help with the problems you’re seeing.