Stop OnCollisionEnter executing twice on one collider yet atleast once PER collider?
I wasn't certain of the best way to phrase this question but I hope it's clear enough. Basically I have a short range particle projectile of sorts that can hit multiple targets and apply damage to each. However OnCollisionEnter is being executed multiple times for each collider, sometimes so many times that it brings the enemy from full health to dead in what would appear to be a single hit.
Initially I thought deactivating the projectile on collision might help but due to the nature of the projectile I have it set to deactivate after a set amount of time otherwise it deactivates too quick to be seen if I'm close to the target. Even if I stand as far back as the projectile can reach the sudden deactivation upon collision results in an odd visual appeal.
So I tried every solution I could find on google such as using a collided bool like so:
void OnCollisionEnter(Collision col)
{
if (!collided && col.transform.CompareTag("Enemy"))
{
collided = true;
enemies.Add(col.transform);
attackMaster.CallEventHitEnemy(col.transform);
}
speed = 0;
}
Or using int variables hitCounter/maxHits like so:
void OnCollisionEnter(Collision col)
{
if (col.transform.CompareTag("Enemy"))
{
enemies.Add(col.transform);
for (int i = 0; i < enemies.Count; i++)
{
attackMaster.CallEventHitEnemy(col.transform);
}
}
speed = 0;
}
Both of these methods did in fact limit the OnCollisionEnter Calls but they also limited the collision to only ONE collider within the radius of my projectile. I actually even tried handling the collision from the enemies end and still when I employ either of the two above methods only one enemy receives damage. Please if anyone knows how to limit collision to once per collider but still allow for multiple colliders to receive the collision at one time I'd greatly appreciate it!
Answer by xxmariofer · Mar 18, 2019 at 11:42 AM
enemies is a list with the transform of the collider, you can check in the if if the collider exists already in the list like this
void OnCollisionEnter(Collision col)
{
if (col.transform.CompareTag("Enemy") && !enemies.Contains(col.transform))
{
enemies.Add(col.transform);
attackMaster.CallEventHitEnemy(col.transform);
}
speed = 0;
}
Wow that's brilliant I don't fully understand how this works but it does! Would you care to break this down for me? I had actually found a way to achieve the behavior I wanted from the enemies end, turns out all I had to do (at least when handling it from the enemies end didn't test from projectile) was set int hitCounter and maxHit to public.
I guess as private variables when one collider was hit the hitCounter++ was called on all active instances of the script. I was about to submit my answer when I saw your answer. It's amazing how one line of code can do so much! Definitely a far more elegant and cleaner solution than $$anonymous$$e thank you so very much!
you have a list called enemies with all the enemies hitten by the bullet, so you can check if the object that has just collided is in that list, if its not it means it has never collided so you call the calleventhitenemy :) and yourissue what it feels is that you were using static variables, public and private variables can not affect in such a way.
Ahh ok! Thank you very much for taking the time to clarify that for me! About the other bit that's super odd because I could swear I wasn't using static variables could it have been something to do with the delegates?
Your answer
Follow this Question
Related Questions
Collision Detection between two different Prefabs doesnt work 1 Answer
If Statement not working properly - Comparing game objects 0 Answers
Game Objects wont appear after restart 0 Answers
how do i collide and kill the enemy while pressing space Unity 5 C# 2 Answers
PhysX: GeometryQueries - Is there a reason for why this haven't been fully exposed? 0 Answers