I am trying to Instantiate a new “Player” after it dies. But can’t start a Coroutine. All objects are active I don’t understand where from this error came.
Here is the code:
Updated the code this is the whole picture of the code.
Part where “Enemy” gives damage to the player:
private IEnumerator AttackUnit()
{
while(true)
{
if (player != null && Vector3.Distance(transform.position, player.transform.position) <= EnemyAttackRange)
{
// Attack Player
player.GetComponent<PlayerAction>().TakeDamageFormEnemy(EnemyDamagePerAttack);
if (player == null)
{
// Player is dead
StartCoroutine(UpdatePath());
break;
}
}
else
{
StartCoroutine(UpdatePath());
break;
}
yield return new WaitForSeconds(EnemyAttackSpeed);
}
yield return null;
}
Part where “Player” takes damage:
public void TakeDamageFormEnemy(float dmg)
{
CurHpLvl = CurHpLvl - (int)(dmg - PlayerStats.CharArmor);
if (CurHpLvl <= 0)
{
// Initiate dead of the Player
Debug.Log("Player is dead");
spawn.StartCoroutine(spawn.RespawnAfterDeadCorutine());
Destroy(gameObject);
}
}
And the coroutine it self:
public IEnumerator RespawnAfterDeadCorutine()
{
yield return new WaitForSeconds(3f);
Debug.Log("RespawnCorrutine is worked out");
Instantiate(PlayerPref, new Vector3(transform.position.x, transform.position.y, transform.position.z), Quaternion.identity);
yield return null;
}
coroutine is attached to the EmptyGameObject in the scene that is always active.
I have searced other question with this problem but did’t find the solution for my case here is the links:
Ok this post makes me sad because there is no answer for so long. TLDR, so I’ll just explain how it all works, and there’s got to be an error in one of them
You define (write-it) a coroutine inside of your classes (for example in Monobehavior class). You then drag and drop it onto a gameObject (GO) within the scene. This GO will now be called “carrier”.
If your behavior does something like this.StartCoroutine( previouslyDefinedOne() ), then as long as the carrier AND this component (monobehavior) are active and are not deleted, everything will be fine.
because we’ve called this.StartCoroutine which is equivalent to StartCoroutine, we made it a responsibility of THIS monobehavior on the carrier to maintain (look-after) and run that launched coroutine.
you could also make another component on some other, alien gameObject to be responsible of your coroutine. In that case, as long as you have a reference a needed component, you can start your routine on its behalf, like this: myAlienComponentReference.StartCoroutine( myLocalyDefinedOne() ) As long as the alien-carrier AND alien-monobehavior component are active and are not deleted, everything will be fine.
This means you can define function in one monobehavior and force a completely different, outsider-monobehavior (ex. a monobehavior with absolutely different set of instructions) instance to run it.
Couple of side notes:
you never invoke coroutine like a normal function. Instead, alsways launch it through StartCoroutine.
You can even store reference to the resulting launched coroutine, which might sound unusual. You do it like this:
Such reference acts like a “rope”, allowing you to for example, prematurely stop the coroutine by calling myAlienComponentReference.StopCoroutine( myCoroutineReference )
Coroutine’s should have at least one yield statement and should always have a return type as IEnumerator, not void or anything else
Why dont yout try to use the overloaded method of StartCoroutine (string name)… as long as you have the same name i believe you can simply do this:
spawn.StartCoroutine("RespawnAfterDeadCorutine");
And that should make the coroutine start… If you need the monobehaviour who started this coroutine to still exist (which i’m not entirely sure about), i can imagine two workarounds. Either you dont start your coroutine from player but you call a method in spawner, which will then call the coroutine. Or you can set a value in spawner (E.g: spawn.respawn = true ), and in the update do something like this:
public void Update () {
if (respawn) {
StartCoroutine (/*However you wanna start it*/);
}
}
I say Dont put the coroutine in the Player gameobject thats gonna get destroyed…Place the script on an empty gameobject and give it a namespace of spawner, a DoNotDestroyOnLoad method, and a reference to the player script and prefab…Done.
Debug.Log("SpawnScript and object is active " + gameObject.activeInHierarchy); returns false, but I don’t understand how it’s possible if object and a script is actualy active.
It’s acting as if it has an inactive parent. None of the parents of the spawn script are inactivated at any point during the games execution? And the script is always enabled?
If everything looks to be in order, Perhaps create a new empty game object and attach the script to that game object and then see what debug.log says then? You’ll probably have to modify a few things to make sure they’re still working.