Search Unity

OnTriggerEnter2D inconsistently detecting collisions

Discussion in '2D' started by montag64, Jul 16, 2014.

  1. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    I have recently come across the same issue that almost everyone comes across when building a 2D platformer game. It's not unique to Unity. When moving horizontally in game from a square platform to a slope, or from walking across flush aligned square platforms, my character's collision box gets caught on the top edge nearest the player. The standard way to get around this (as said in most tutorials) is to place a circle collider on the character's feet instead of a box collider. This works perfectly for walking, but makes it very hard to leap from one small platform to another (like Mario leaping from a ? box to another ? box). The bottom left and right corners are lost when going to a circle collider, so the character basically "falls" off the sides where he should still be able to stand. For example, Mario's heels might be on the edge of a pipe, but he doesn't slide off the corner. The noob solution would be to make the circle collider bigger so that he can stand on the edge, but then Mario's feet have an invisible wall around them that tends to get caught on ledges when trying to jump upwards.

    (Please note when I say collider here, I mean 2D collider)

    I figured the best way would be to devise an algorithm that alternates between a circle collider when on joined platforms (more than one) and a box collider when on "island" platforms. This would work in three cases, when moving from platform to slope, across platform to platform, and also where standing on edge.

    box.PNG circle.PNG
    box case circle case

    I coded this, incorporating a 2D box collider, a 2D circle collider, while the body had a 2D box collider at all times. I disabled/enabled the circle and box colliders based on a circle collider trigger about 1.1 radius that detects objects in the platform layer. When one platform enters, its added to a list, and when one moves out of vicinity of the player, it's removed from the list (OnTriggerEnter2D and OnTriggerExit2D. When the list exceeds one object, the box turns to a circle, and vise versa. This is where it gets weird...

    Everything works exactly as expected, 95% of the time. The issue is after as many as 500 trigger collisions, or as few as 20 (usually more) the OnTriggerEnter2D command detects the same object twice, OR more likely, the OnTriggerExit2D doesn't execute every time an object exits. This tends to happen most often when trying to jump into a corner like at the right of the picture. I added a counter in enter and a counter in exit, and the enter counter was always one greater than it should be (when jumping off the floor to exclude it). Also, in the list, there is always some residual object I landed on previously that was never removed, even though I'm nowhere close to it.

    I have tried the following things to no avail:

    Disabling all collision boxes except body - problem still occurs
    Ensuring that no collision box/trigger boxes do not intersect and overlap
    Increasing/decreasing the trigger circle radius
    Changing the trigger collider to a box instead of circle
    Attaching the trigger to the parent
    Attaching the trigger to the child
    Checking overlap of platforms (no duplicate overlaps in Z)
    Running as .exe and not in editor mode.

    The cheap way to fix this issue would be to purge the list every few seconds (minutes?) and thus no object would be orphaned in the list for long, but that is less than ideal. Does anyone have any ideas why the trigger is not always detecting the player's exit? I wonder if this is similar to the "bullet through paper" problem, and that the time in between frames is not enough to calculate a trigger. I would really prefer not to change the timestep to allow more calc time. I would also prefer not to disable gravity as I am doing other things while walking to the player, plus that seems like putting a band-aid on it. Does anyone have any ideas for fixing this issue, or maybe a better algorithm that works more than 95% of the time?

    I also have a repro proj ready to go. I appreciate your guidance on this.
     
  2. Pyrian

    Pyrian

    Joined:
    Mar 27, 2014
    Posts:
    301
    I have an algorithm on one of my enemies that does this successfully, but man, it was difficult to get working. But all the bugs I found were mine. Are you absolutely sure you're doing everything right when you hit two colliders in the same physics update?

    That being said... I think your solution is not ideal. You could use edge colliders for your geometry and not have this problem. (Also, I'm told they're faster.) You could use small circle colliders at the corners of your character's box collider and not have this problem. You could do a lot of things, without having to script anything.
     
  3. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    Thanks Pyrian.

    To the best of my knowledge, I am. I really tried everything else like moving collision boxes apart from each other, etc and I cannot seem to get the problem to go away. The thing that gets me is that in theory, this should work without a hitch.

    How exactly did you implement this algorithm with your enemies? And by edge colliders do you mean edge colliders on the platforms or on the character's feet?

    I will try small circles or some combination. That is a good idea, thanks.
     
  4. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    402
    You should try a test with a bouncing ball for about an hour. Increment by 1 each time OnEnterTrigger fires and Decrement by 1 each time OnExitTrigger fires.

    ... you'll end up at +35 after an hour.