I know the best answer has been chosen and this issue is super old, but I’ve hit this exact case. Let me outline what I did to have the issue, and at the bottom I’ll provide my solution. Hopefully this helps someone out there:
First, create a Prefab with an attached script where it creates another instance of the same prefab, like so (This code is a simple illustration that creates the problem, not meant to be perfect):
using UnityEngine;
using System.Collections;
public class Respawnable: MonoBehaviour {
private int hp;
public GameObject guyPrefab; // The same type of prefab this script will be linked to
void Awake()
{
hp = 10;
}
void Update()
{
// Is this dead?
if(hp <= 0)
{
this.gameObject.SetActive(false);
StartCoroutine(Respawn(15f));
}
}
IEnumerator Respawn(float timeToRespawn)
{
float timer = timeToRespawn;
while (timer > 0)
{
timer -= Time.deltaTime;
yield return null;
}
Instantiate(guyPrefab, aPosition, Quaternion.identity);
Destroy(this.gameObject);
}
}
For me, the prefab that is instantiated during that respawn coroutine will be a copy of the instance of the prefab that called the coroutine as long as that coroutine is part of a script attached to the original instance of the prefab. Phew! That was a mouthful. Hopefully This makes sense.
To illustrate, I’ll provide a screenshot:
In this scene I had 13 instances of a prefab that represented a gravestone. When the gravestone was “destroyed”, it would start a coroutine to respawn a new instance of itself (exactly like in the example code above). In this particular test, I destroyed grave (4). As you can see, instead of the expected grave(Clone) we instead got a grave (4)(Clone), as though it was instantiating an instance of the now destroyed grave (4)! But I wanted a fresh instance of the prefab!
robertbu pointed out a few concerns about the problem. First off, let me assure you that I did not change any variables in the prefab itself. I prove this because I made one important script change that fixed the problem. I’ll get to this below. Second, as the GameObject variable is set to be a prefab, and that variable is only referenced when it is time to instantiate, I’m guessing that I’m not spawning an instance of the game object, though I suppose I could be wrong and am missing something. Finally, the prefab is definitely not being overwritten in the code, as it is only referenced when instantiating.
And now the solution:
I simply created another script to facilitate. This script has a GameObject variable where I set the prefab, and then the other class calls the external coroutine and things work fine:
using UnityEngine;
using System.Collections;
public class RespawnManager : MonoBehaviour {
public static RespawnManager instance;
public GameObject guyPrefab;
void Awake()
{
if(instance == null)
{
instance = this;
}
}
public IEnumerator Respawn(float timeToRespawn, Vector3 aPosition)
{
float timer = timeToRespawn;
while (timer > 0)
{
timer -= Time.deltaTime;
yield return null;
}
Instantiate(gravePrefab, aPosition, Quaternion.identity);
}
}
public class Respawnable: MonoBehaviour {
private int hp;
void Awake()
{
hp = 10;
}
void Update()
{
// Is this dead?
if(hp <= 0)
{
this.gameObject.SetActive(false);
StartCoroutine(RespawnManager.instance.Respawn(15f, this.transform.position));
}
}
}
This successfully creates a clean instance of the prefab.