Why is my script instantiating a (clone)(clone) from a prefab

I have a spawnable component on a gameobject. Now the idea is that this object can spawn clones of itself but I don’t want it to spawn a clone of the clone. I want it to spawn from the original prefab.

My code looks like this

public class Spawner : MonoBehaviour
{
    public Spawner spawner
    // Start is called before the first frame update
    void Start()
    {
     
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            Instantiate(spawner.gameObject, Vector3.zero, Quaternion.identity);
        }
    }
}

On runtime I spawn a new Spawner gameobject which is a clone of the prefab. This prefab can then spawn more prefabs by pressing E. However it isn’t cloning the prefab. It appears to be cloning a clone of it

Can anyone tell me why this is happening?

I’m instantiating from an original prefab, surely it would just be a clone of the prefab, ie Spawner(Clone)

I’m getting Spawner(Clone)(Clone)

It sounds like you’re having an issue with the way that an instantiated prefab updates its references. If you have any reference from one component in a prefab pointing to another component on the same prefab, then when instantiating, the reference will point to that component on the instantiated copy. This is nearly universally the right decision; could you imagine the chaos if every reference on an instantiated copy pointed to the prefab instead of itself? Even the simplest things like a reference to a renderer would be utterly broken.

Unfortunately though, there is no way to tell Unity “When you instantiate this, please don’t update this reference, I know it’s unusual but that’s what I want this time.” You’ll have to work around it by holding that reference somewhere else where it won’t be modified. One way to do this would be to have the instantiated copy use the same reference that was used to instantiate it in the first place - e.g. it finds the prefab reference on the manager that spawned it, for example.

1 Like

@Ray_Sovranti Thanks for the detailed response Ray. This makes a lot of sense and I’ll implement your workaround.

The reason that this is an issue in the first place, is because the actual gameobject has a bunch of other scripts on it and when the clone of clone is instantiated it calls the start methods on all these components and it’s causing a bunch of errors in the console as if the instantiated object has already called the start method.

I add a line renderer in one of the components start methods and it appears that it’s already added at the point of it being cloned. I guess I expected it to be spawning as a completely fresh object.

I would also recommend to store the prefab reference somewhere else.

However if you really need the instance to have a reference to his own prefab, this is possible but requires some additional work. First of all when you instantiate the prefab in code, you just have to make sure you set that reference again to the actual prefab on the newly instantiated object. If you have instantiated your prefab in the editor by dragging the prefab into the scene, you would need to manually assign the actual prefab reference there. From that point on you shouldn’t have any issues as long as you always re-set the prefab variable in newly instantiated objects.

Since this approach is quite error prone as you can easily forget to assign the reference in the scene or you forget to copy the reference when you call Instantiate, storing the prefab reference elsewhere is the better approach. You could even use a ScriptableObject like this:

[CreateAssetMenu]
public PrefabRef : ScriptableObject
{
    public Transform prefab;
}

So for every prefab you can create another instance of that scriptable object in your project. The script on the prefab would simply reference this PrefabRef instance and the prefab variable in that asset could simply reference the prefab. So they are referencing each other. References to other assets that are not part of the prefab will stay.

Thanks for your input Bunny.

I’ve actually decided to create a PrefabManager class which will return all the different prefabs I want depending on their ID. I’ll make it a singleton aswell to make it readily available.

I’m going to have to take a good look at scriptable objects because I see them being mentioned all the time but have never actually used them.

Yes, reducing the prefab to an ID is also quite handy if you need saving / loading at some point since referencing assets from runtime serialized data is kinda tricky.

1 Like