Unity instantiating more than one prefab

Good morning, So my class group has been tasked to make a game and we have been stuck on how to solve our issue with a script that instantiates a prefab after deleting the first prefab. What happens is sometimes the prefab will be duplicated several times over as shown in the link provided.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/*
* ATTACH THIS SCRIPT TO THE OBJECT THAT IS BEING DESTROYED
*/

public class breakObject : MonoBehaviour
{
// Spawns destroyed prefab
public Transform destroyedObject;
// Strength of object
public float objectStrength;
// The distance that the force effects the object
public float objectExplosionRadius;
// The distance that the "explosion" sends the pieces
public float explosionPower;
// The force that sends the broken pieces flying up
public float upwardsExplosion;

// When object hits the prefab hard enough destroys the object.
private void OnCollisionEnter(Collision collision)
{
    // Anything that hits the prefab with greater force than the strength of the object is destroyed.
    if (collision.relativeVelocity.magnitude > objectStrength)
    {
        Destroy(gameObject);
        Instantiate(destroyedObject, transform.position, transform.rotation);
        destroyedObject.localScale = transform.localScale;
        Vector3 explosionPos = transform.position;
        Collider[] colliders = Physics.OverlapSphere (explosionPos, objectExplosionRadius);

        foreach (Collider hit in colliders)
        {
            if (hit.attachedRigidbody)
            {
                hit.attachedRigidbody.AddExplosionForce(explosionPower * collision.relativeVelocity.magnitude, explosionPos, objectExplosionRadius, upwardsExplosion);
            }
        }
    }
}
}

This script is attached to the parent object of the prefab. We have tried commenting out several lines to see if it would change anything, but now its believed to be something with unity’s physics. The Prefab does have a rigid body attached and a box collider.

That’s not a bug, that’s a feature!

OnCollisionXXX can be called multiple times. For example:
8434130--1117040--upload_2022-9-12_14-23-50.png
A will fall due to gravity and touch B and C at the same time. If you add OnCollisionEnter to A, then you will get two calls, one coming from B and another coming from C. If you do the same for B, then you will get one call (A).
For example (just a print):

void OnCollisionEnter(Collision collision)
    {
        print($"Collision with {collision.collider.name} at {Time.time} seconds");
    }

If you add a Destroy on top, nothing changes:

void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
        print($"Collision with {collision.collider.name} at {Time.time} seconds");
    }

This is probably because of how these calls are scheduled, or maybe because the object is not destroyed immediately.
BTW, using DestroyImmediate is not allowed during OnCollisionXXX.

One solution is to check if the object is enabled. If so, do the “thing” (print in this case) and then destroy it. From the example above, this will produce only one call:

void OnCollisionEnter(Collision collision)
{
   
      if (!enabled)
            return;

      print($"Collision with {collision.collider.name} at {Time.time} seconds");  
      Destroy(gameObject);     
}
1 Like