- Home /
I solved it by myself. The issue wasn't due to Unity, but because of my code.
OnCollisionEnter method iterating multiple times after each collision.
So, I'm running an OnCollisionEnter method in my Boss enemy to detect if a spell did hit him. It's a pretty usual thing, it never fails.
The problem here is that for each consecutive spell hit, the number of times it iterates through the collision detection increases.
It goes like this:
Hit 1 - 1 Hit.
Hit 2 - 19 Hits.
Hit 3 - 36 Hits.
...
So... It doesn't really work for me. Each spell deals one Hit Point. This means that the Boss should die in ~20 seconds assuming one never misses a shot. Instead, what happens is that the Boss dies in ~5 seconds because of these multiplied hits. Does anyone know why is that? Here are a few details that may or may not interest you.
The Boss has a Rigidbody set for full constraints lock, and CCD (Continuous Collision Detection). He also has a Box Collider of its size with Trigger set to false. There are no other Colliders and/or Rigidbodies in its children. He never uses gravity. He never moves.
The spell has a Rigidbody with no constraints locked and CCD enabled. It has a Non-Trigger Box Collider of its size. There are no other Colliders and/or Rigidbodies in its children. It never uses gravity. It is always in movement.
Any help is profoundly appreciated. Thanks in advance.
Are you destroying the spell promptly on collision, or is it allowed to pass through? If it's allowed to pass through, you could store the object that hit the boss in a list and ignore it if it pops up again as a naieve solution:
using System.Collections.Generic;
using UnityEngine;
public class Boss : $$anonymous$$onoBehaviour {
List<GameObject> collidedObjects;
void Awake() {
collidedObjects = new List<GameObject>();
}
void OnCollisionEnter(Collision other) {
if (collidedObjects.Contains(other.collider.gameObject))
return;
collidedObjects.Add(other.collider.gameObject);
// Take damage, etc
}
}
In this approach, the list will eventually contain a bunch of null objects if at some point the spells are destroyed. You might want to run a coroutine to prune it occasionally. However, if you're destroying the spell on collision, you can try experimenting ins$$anonymous$$d with using the OnCollisionStay callback.
I'm not destroying the Game Object since it is an unnecessarily heavy loaded operation. I use an object pooler from which I spawn the projectiles.
Once the projectile hits the boss, it is instantly deactivated to prevent issues. But apparently not all of them.
I've never had an issue like this, can you link its collision code?
It's like...
private void OnCollisionEnter (Collision collision)
{
if (collision.tag == "Projectile")
{
[...] // Updates health bar and boring stuff that ain't needed :)
health--;
}
[...]
}
This doesn't really fix your problem or explain it but what if you put the OnCollisionEnter $$anonymous$$ethod on the spell? So when it collides, get the boss health and increment it down before destroying the spell object. I had a similar issue on a different type of game and that was how I got around it. I've also found OnTriggerEnter to be a bit more forgiving.
This can actually work. But I wanted to understand the issue to prevent future issues as well.