OnTriggerEnter2D not detecting hits consistently

Hi!
I’ve been following the course (Unity 2D RPG: Complete Combat System) and everything seems to have gone fine so far, but now I’m running into an issue with the collision detection. It seems that hits are only detected after I’ve moved the player a little bit.

In the picture below, I’ve walked the player to the enemy and swung my sword. This detected a hit, and logged the updated enemy health in the console, as expected. However, when I repeatedly swing my sword after without moving the player, hits are no longer detected. I haven’t moved, the enemy hasn’t moved (I disabled the enemy movement for this example).
When I move only a little bit and swing the sword again, it does detect a new hit correctly. Then, when I repeatedly swing without having moved, the same problem occurs.

Does anyone have any ideas what the problem might be? I’ve also added screenshots of my scripts below. Thanks in advance :blush:

DamageSource:
image

EnemyHealth:

Hits are only detected (OnTriggerEnter2D) when you enter the collision. It appears your player hasn’t exited the trigger again, so it no longer detects collisions because you are still in the collider. When you move, you exit the collider and the same thing happens. You can check this by having the OnTriggerExit2D log to the console.

private void OnTriggerExit2D(Collider2D other)
{
    Debug.Log($"{other.gameObject.name} exited the collider");
}

@bixarrio, thank you for your reply!

I probably forgot to mention, but the collider’s GameObject is enabled and disabled as I start and finish the slash animation, meaning that the OnTriggerExit is activated as soon as the collider object is disabled (I’ve tested it using your code snippet, thank you for sharing it).

For testing purposes, I’d created a new empty object with a BoxCollider2D and put it on top of the slime. I’d attached the same DamageSource script to it and enabled and disabled the object repeatedly, without moving anything, and that did work as expected. So i’m definitely confused :sweat_smile:

To make sure it didn’t have to do with any possible differences between a BoxCollider2D and a PolygonCollider, I’d also replaced the PolygonCollider with a BoxCollider2D and made it bigger, but still no luck.

I’m trying to figure this out. Can you show me the slime and where its EnemyHealth component sits? Are you sure the collider gets disabled?


Edit
I don’t have this course and I’m purely going off of anything you share here so the more you give me the easier it would be.

Hi!

I do also have a little update myself.

(^ I’ll get to this in a little bit)

So what I’ve noticed, is when the collider that contains the OnTriggerEnter2D code does not contain a parent object with a Rigidbody2D, everything works. However, when I placed my test collider as a child of my Player (with Rigidbody), it no longer works. The BoxColliderComponent displays an ‘Attached Body’, which references the player’s rigidbody (see first image).

When I then add another Rigidbody2D to the collider object itself, it does work again as expected. (The Attached Body in the collider references its own rigidbody, see second image).

So I guess it has something to do with the way collisions and rigidbodies are handled by/handling eachother? I’m glad that this is a fix, but I’m not sure why this behaviour happens and whether it is a proper fix. Could you enlighten me?

Image 1:
image

Image 2:

Back to your reply, thanks for letting me know you didn’t know/have the course, I wasn’t aware. This is what the hierarchy looks like with a quick description. If you need more inspector details, let me know!
image

My 2 questions above was pointless, really.

I wanted to see on which game object the EnemyHealth component is because I thought the slime might actually have died and the health destroyed one of the child game objects instead of the whole thing. But then I saw the console and realised the slime is still alive.

I also asked if you were sure the collider got disabled but you did say that the code reflected as much, so yet another pointless question.

I tested it and managed to reproduce the issue. If I enable/disable the parent object, the collisions happen as expected, but not if I enable/disable the child object with the collider. However, if I enable/disable the component (PolygonCollider2D) on the child object it works as expected. Make sure you are referencing the correct thing when enabling/disabling the collider. If you are, perhaps it is something that will be addressed later in the course.

It appears like the issue is caused by some optimisation in the physics engine. If you change a value in the Rigidbody2D while it’s no longer working, it suddenly reports a change in the console. It seems the rigidbody is not processing the subsequent enable/disables and then, when it’s forced to do so, it detects the change

1 Like

Hi bixarrio, thank you for trying to reproduce the issue :blush:

So, does disabling/enabling the collider directly (instead of the GameObject) work for you? I still have the same issue, both when trying to enable/disable the GameObject and when trying to enable/disable the Collider component. (Note: the collider (object) that is being enabled and disabled does not contain a rigidbody by default. I’ve only added one to make it work myself, but the instructor does not add one in the course).

In the course, the instructor enables/disables the actual gameobject (not the collider). If I saw correctly, he also has this issue, but since he is moving his character around a lot, he hasn’t noticed or mentioned it so far. I’m still following the course, so maybe he discovers it in a later video, but I’m not sure.

What do you mean with this sentence? “No longer working” as in disabled? “Changes” as in velocity, collisions, etc?

When you slash and the collider is no longer causing damage, and you then go to the Rigidbody2D on the parent and change something like Collision Detection to another value. It seems to force the rigidbody to re-evaluate the physics. Bear in mind that I don’t have a weapon enabling/disabling my collider. I was doing it manually in the inspector.

So, I would start my test and the ‘enter’ is detected. Then I disable the child object and the ‘exit’ is detected. When I re-enable the child object, nothing happens. If I then go to the Rigidbody2D (on the parent) and change ‘Collision Detection’ from ‘Discrete’ to ‘Continuous’ (or vice versa) the ‘enter’ is immediately detected. I did some quick (<- operative word) search on the unity forums but couldn’t see anything related to this.

1 Like

Hi @bixarrio, thank you for the elaboration on your answer :blush:

Based on your answers, some googling and trying, I think I found what is causing the issue:

So, because my weapon collider is a child object of my player object and the collider object itself does not contain a rigidbody, its collisions are detected using the rigidbody of the player object. Apparently, rigidbodies have a sleep threshold and can basically fall asleep when the rigidbody’s movement/velocity/activity(?) is below that threshold. (I never knew rigidbodies had this behaviour).

Usually, rigidbodies tend to wake up when collision events happen, but because my collision is a child object without its own rigidbody, my player’s rigidbody for some reason does not wake up. Therefore, as long as my player’s rigidbody isn’t moving, it is not detecting collisions on child colliders.

Fortunately, I have found a few fixes to the problem:

  1. Add a rigidbody to the weapon collider object.
  2. Disable sleeping for the player’s rigidbody (there is a Sleeping Mode setting on the Rigidbody2D, which I could set to Never Sleep).
  3. Programmatically wake up the player’s rigidbody whenever I trigger an attack.

Option 1 and 3 seem most viable to me, I’d rather not disable sleeping altogether, because I’m not sure yet what the consequences will be for performance.

So, thank you very much for your help @bixarrio :heart: Everything seems to be working fine now!

2 Likes

Yeah, when the physics engine ‘perceives’ an object as no longer moving (or almost not moving within a threshold) it will stop processing (go to sleep). It’s simply because there is no further need for it at that point. Good find.

Personally, I’d go with option 2. The player is the most important object in the game. As long as you only do this for the player, I don’t think you have to worry about the performance. It really just means the physics will continue to be checked, even if the player is not moving.

4 Likes

That actually does make sense, thanks!

@Stephen_Hubbard Something to check on?

1 Like

Rigidbodies and colliders can be so annoying sometimes. I’ve had issues like this in the past and they can be frustrating! I remember like a year ago I was trying to debug something like this for over an hour and it was just because I accidentally attached a non-2d rigidbody instead of a rigidbody2d haha. Stuff like that is so tilting. Glad you mainly got it sorted though!

1 Like

Hi @Stephen_Hubbard,

First of all, thank you for the awesome course! I’m having a blast so far and I’m learning a lot.

I was wondering, doesn’t this issue also exist in your project (at least until the end of the Combat section of the course)? I haven’t noticed it in the lectures yet, but that might also be because you move the player a lot as you hack 'n slash your way through the slimes.

Yes! Especially when troubleshooting gets a bit more technical, but I’m glad there are people like you guys or on other forums that can help out when it gets too difficult.

Thank you! :heart:

1 Like

I don’t think it is! But I need to do some testing at that point in the course to see if it exists for me too!

Privacy & Terms