Search Unity

Proper collision detection with CharacterController?

Discussion in 'Physics' started by Juice-Tin, Jan 21, 2015.

  1. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    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!
     
    Last edited: Jan 21, 2015
    BrainSlugs83 and Jack_Truong like this.
  2. Nubz

    Nubz

    Joined:
    Sep 22, 2012
    Posts:
    553
    Probably a dumb question but are you sure there is colliders on the objects and they aren't set to isTrigger?
     
    EpicVenge likes this.
  3. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    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.
     
    dimmduh1 likes this.
  4. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    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)
    Code (CSharp):
    1.     CharacterController controller;
    2.     float distance;
    3.     int platLayer;
    4.  
    5.     void Start(){
    6.         controller = GetComponent<CharacterController>();
    7.  
    8.         //Distance is slightly larger than the
    9.         distance = controller.radius + 0.2f;
    10.  
    11.         //First add a Layer name to all platforms (I used MovingPlatform)
    12.         //Now this script won't run on regular objects, only platforms.
    13.         platLayer = LayerMask.NameToLayer("MovingPlatform");
    14.     }
    15.  
    16.     public void Update(){
    17.         RaycastHit hit;
    18.  
    19.         //Bottom of controller. Slightly above ground so it doesn't bump into slanted platforms. (Adjust to your needs)
    20.         Vector3 p1 = transform.position + Vector3.up * 0.25f;
    21.         //Top of controller
    22.         Vector3 p2 = p1 + Vector3.up * player.controller.height;
    23.  
    24.         //Check around the character in a 360, 10 times (increase if more accuracy is needed)
    25.         for(int i=0; i<360; i+= 36){
    26.             //Check if anything with the platform layer touches this object
    27.             if (Physics.CapsuleCast(p1, p2, 0, new Vector3(Mathf.Cos(i), 0, Mathf.Sin(i)), out hit, distance, 1<<platLayer)){
    28.                 //If the object is touched by a platform, move the object away from it
    29.                 controller.Move(hit.normal*(distance-hit.distance));
    30.             }
    31.         }
    32.  
    33.         //[Optional] Check the players feet and push them up if something clips through their feet.
    34.         //(Useful for vertical moving platforms)
    35.         if (Physics.Raycast(transform.position+Vector3.up,-Vector3.up, out hit, 1, 1<<platLayer)){
    36.             controller.Move(Vector3.up * (1-hit.distance));
    37.         }
    38.     }
     
    Ghosthowl, RustDust, dimmduh1 and 6 others like this.
  5. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    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?
     
  6. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    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 :)
     
    minhanh26061995 likes this.
  7. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    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. :)
     
  8. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    Not mixed up with but I thought it was more integrated with the physics engine. Good information though!
     
  9. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    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. :(
     
    minhanh26061995 likes this.
  10. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @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.
     
    Harinezumi likes this.
  11. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Ah ya beat me to it Juice, lol
     
  12. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    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.
     
  13. Erind

    Erind

    Joined:
    Jul 23, 2014
    Posts:
    56
  14. ghostbuster96

    ghostbuster96

    Joined:
    Feb 28, 2015
    Posts:
    17
    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
     
  15. Erind

    Erind

    Joined:
    Jul 23, 2014
    Posts:
    56
    this problem is fixed with unity 5.2 i think
     
  16. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @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.
     
  17. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    @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.
     
  18. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @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.
     
  19. roka

    roka

    Joined:
    Sep 12, 2010
    Posts:
    598
  20. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    In Unity 5.4 Alpha 5 we're exposing a "recovery" mode of CharacterController. This might help with the problems you're seeing.
     
  21. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @MortenSkaaning

    What exactly is a "recovery" mode? and does this apply to the issue in this thread, or the one roka is talking about as they are not related.

    Realistically the CharacterController should just collide with things even when its not moving, and from any direction. I can only assume it was done this way to limit the number of physics checks needed, but it really really really goes against what would be a logical assumed functionality of the CharacterController the way it acts right now.

    More specifically, for my situation, a collision needs to be detected any time a mesh is built. I do not have a moving object, but instead a mesh that gets modified, which causes verticies to move which SHOULD cause the collision, but doesnt.
     
  22. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    The main reason I reconstructed character controller with a capsule collider and rigidbody was because of these issues plus the fact the character controller's callbacks generate far too much garbage, so this recovery mode might solve some issues.

    Also if anyone's reading: mesh colliders need to be convex in 5, you can't have a moving mesh collider that isn't.

    The roadmap seems to hint at being able to construct a convex/soup/mesh collider from convex shapes via a library though.
     
  23. Dan2013

    Dan2013

    Joined:
    May 24, 2013
    Posts:
    200
  24. JosephHK

    JosephHK

    Joined:
    Jan 28, 2015
    Posts:
    40
    The fix is awful.

     
  25. Dan2013

    Dan2013

    Joined:
    May 24, 2013
    Posts:
    200
    @JosephHK

    I did a simple test with Uniyt 5.5.
    If I move a kinematic rigidbody with box collider to a static Character Controller (not moving), I see the penetration still happens. Like Juice-Tin said, it is impossible to implement some game mechanisms such as moving platforms.
    Character Controller issue.jpg

    In addition, if you search "Character Controller" a lot in the forum. You will find many other issues of it... :(
    I had given up using it long time ago...
     
    Last edited: Jan 18, 2017
  26. JosephHK

    JosephHK

    Joined:
    Jan 28, 2015
    Posts:
    40
    It is because the Character Controller only calculates the movement when you call CharacterController.Move.
    And when you call it, the overlap recovery can occur.
    But unfortunately, at least to me, lifting the CharacterController up onto the top of the collider of a rigidbody is not a good recovery.
     
  27. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    I gave up forever ago on this issue. The only acceptable result is not to use Unity's built in CharacterController for anything, its utterly useless. The "recovery mode" is an even bigger joke than the actual issue in the first place.

    Its really rather sad that one of the basic components is broken in a most basic way, and the dev's at unity have yet to fix it in over a year.

    @MortenSkaaning - Do you have any further input on this since, ya know, last year....
     
  28. silentneedle

    silentneedle

    Joined:
    Mar 14, 2013
    Posts:
    280
    Has this been fixed with 5.6?
     
  29. sgower

    sgower

    Joined:
    Mar 9, 2015
    Posts:
    316
    I'm on 5.6b9 and don't have a lot of experience with Character controllers. I just added a Vive movement script, but I'm seeing really inconsistent behavior. I can drop a huge cube in my scene, and when I move toward it, for part of the cube I'll stop, and other parts I'll pass right through. It doesn't make any sense. I made a video showing this behavior.

     
  30. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Its because the built in Character controller is completely awful. I had so many issues with it, one of which this thread is about (which still doesn't work right). Inevitably you will have to roll you own controller, or purchase an asset off the store is the general conclusion everyone seems to come to.
     
  31. sgower

    sgower

    Joined:
    Mar 9, 2015
    Posts:
    316
    Do you have an asset store asset to recommend for this? To solve the problem in the above video, I added a Physics.Raycast to detect obstacles and stop movement when you get too close to something. It seems to work ok, but it doesn't seem like I should have to do this. Things like characters moving around and walls are pretty common in games, so it's surprising this isn't rock solid given that Unity has been around for several years.
     
  32. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Your particular problem... that is new to me, and you are right, that SHOULD work out of the box no issues...

    The only thing i could think is to check the "collision detection" (i think that's is what its called) drop down on both objects.
    Initially play with the setting on the "character" collider first and see if it works. By default i think its set to discrete or something... This works "ok" but i have seen situations where objects moving even at slow speeds have clipped through other non moving objects even when moving directly in to them, the problem was more obvious when the objects were approached at an angle. There are three options, from "worse" to "best" in terms of how good of collision detection it does... there is also a direct correlation to how cpu intensive each type of checking is with "worse" being the fastest, and "best" being the slowest.

    As far as a recommendation from the asset store I do not have one to give, i went the option where I am writing my own.... mainly because i dislike paying for something that im not sure will work exactly how i need it to, and the asset store is a roll of the dice as far as what you get.
     
  33. silentneedle

    silentneedle

    Joined:
    Mar 14, 2013
    Posts:
    280
    @MortenSkaaning I would be happy this problem could get some attention from the Unity devs.
     
  34. GoalLine

    GoalLine

    Joined:
    Mar 23, 2017
    Posts:
    8
    Good thread, and yes this is still happening. Spanky11's vidoe is exactly whats happening with my project.
     
  35. AlexTuduran

    AlexTuduran

    Joined:
    Nov 26, 2016
    Posts:
    27
    I've relied of CharacterController since day one and build my FPS character around it. Now I see myself forced to either create my own CharacterController or get one from the Asset Store because I can't implement basic things like being hit by objects. This is really disappointing.
     
    Chinin and Harinezumi like this.
  36. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hello, my name is Oscar Gracián author of Easy Character Movement a rigidbody based character controller, which among other features solve this issue related to unity's character controller, and dynamic platforms, it's been designed to be really easy to use and easy to integrate in existing projects.

    If interested please take a look at the asset store, or feel free to message me to support email, I'll be happy to help you.
     
  37. LyesBourahla

    LyesBourahla

    Joined:
    May 30, 2017
    Posts:
    2
    hey i found a simple way to correct this bug :
    try to increase the skin width variable in the character controller but then your character will be a bit looking floating but i think it's less issue then the current one :)
     
  38. Student2013

    Student2013

    Joined:
    Dec 5, 2013
    Posts:
    1
    I fixed my issue with the same problem by moving character each update to zero vector. No collision is missed since :)
     
  39. ayhaab-pasha

    ayhaab-pasha

    Joined:
    Dec 6, 2015
    Posts:
    5
    I was having a lot of trouble finding the solution for abnormal movement. I knew there wasn't any thing to do with the code. This particular line helped me!
    I was having problems when i was enabling Capsule collider. By enabling Capsule Collider with Sphere Collider, the models would move crazily! When I disabled the Capsule Collider, the movement would return to normal, but the models would not collide with structure.
    Reading this comment, i realized i had both, RigidBody and Character Controller enabled! I disabled Character Controller, and every thing was normal again. Thank you!
     
  40. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    393
    pretty sure it's something to do with rigidbody.Sleep()
     
  41. Durium

    Durium

    Joined:
    Feb 1, 2020
    Posts:
    37
    2020 and still no fix to this?
    Anyone know something new? :)
     
  42. hashtagrich

    hashtagrich

    Joined:
    Oct 12, 2020
    Posts:
    1
    Unfortunately, still broken :/
     
  43. RealEfrain12

    RealEfrain12

    Joined:
    Nov 16, 2020
    Posts:
    1
    I think I found a solution for this thread.
    Code (CSharp):
    1. public Transform groundCheck; //make an empty gameObject inside your game (or create one inside your player) then place it a bit lower, and then set that to your groundcheck
    2. public bool isColliding;
    3. public float groundDistance = 0.4f;
    4. public LayerMask collisionMask; //in the editor set this to a specific layer
    5.  
    6. public void FixedUpdate() //Can be Update
    7. {
    8.       isColliding = Physics.CheckSphere(groundCheck.position, groundDistance, collisionMask);
    9.  
    10.      if (isColliding)
    11.      {
    12.            //Write whatever you want to happen once the player has collided with this thing
    13.      }
    14. }
     
    zuuuuuuuu likes this.
  44. tskipurishvilimakrina

    tskipurishvilimakrina

    Joined:
    Nov 20, 2021
    Posts:
    7
  45. BT_RU

    BT_RU

    Joined:
    Apr 24, 2022
    Posts:
    4
    private void Update()
    {
    isMove = _moveInputAxis != Vector2.zero;
    if(isMove == false)
    _characterController.Move(Vector3.forward * 0.000000001f * Time.deltaTime);

    }

    That's how I solved this problem
     
    Kekaku and BRGames_ like this.
  46. BRGames_

    BRGames_

    Joined:
    Jun 24, 2021
    Posts:
    20
    in 2023 still, this is the right solution (at least with Unity 2021) am I wrong? please tell me I'm wrong :D
     
  47. Kekaku

    Kekaku

    Joined:
    Oct 24, 2018
    Posts:
    7
    Solved my problem, thanks! But this is quite tricky, seems like when a character controller is moving, it takes physics collider into account, and can be pushed away correctly.
     
  48. Rogue_Snake

    Rogue_Snake

    Joined:
    Jun 9, 2022
    Posts:
    2
    This is an old thread but found a solution so figured I'd post it. I just when to Edit> Project Settings > Physics and turned on Auto Sync Transforms and Reuse Collision Callbacks
     
  49. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,459
    AutoSyncTransforms should never be used for anything than its original purpose which is backwards compatibility. It has huge performance consequences so no, don't turn that on unless you know exactly what you're doing.
     
  50. Freddie741

    Freddie741

    Joined:
    Dec 5, 2022
    Posts:
    1
    So what's the best suggestion in 2023?
    I have two 2.5d players with a character controller and when they move against each other they pass through.
    Thank you
     
    ramtinq likes this.