- Home /
Coroutine couldn't be started because the the game object 'Spawn' is inactive![SOLVED]
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: http://answers.unity3d.com/questions/1013770/coroutine-couldnt-be-started-because-the-the-game-2.html
http://answers.unity3d.com/questions/709798/cant-start-coroutine-since-object-is-inactive.html
if you're dead sure spawn is active (which I cannot really believe due to the error) you could create a method in your EmptyGameObject class taking over the call to StartCoroutine. if that works it is not possible to call StartCoroutine on a gameobject from an empty one, even though that shouldn't be a problem.
I tried to do so before make it like this "Player dies => Func: void StartCorutineRespawn() "StartCorutine(RespawnCorutine())" But It gives same error. Spawn is active I wold notice if it weren't. Because I monitored it state in play mode. Only if its turned off and then turned on in one frame but I checked all scripts it's not even used in any of them.
This is very strange error.
youre calling a co-routine and then destroying the object that called the co-routine ? well and what happens when you "yield return" where is it going to return? i think thats the problem although im new to unity and c#
my code first looked like this, I tried it like you suggesting.
Player Script:
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.PlayerRespawnIfDead();
Destroy(gameObject);
}
}
And the Respawn Script:
public void PlayerRespawnIfDead()
{
StartCoroutine(RespawnAfterDeadCorutine());
Debug.Log("Start Respawning");
}
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;
}
Still gives the same error.
hmm i dont know i dont have a clear vision of your script but try deleting the player from the scene and pass the prefab as a variable to the Spawn script and spawn him from there void OnEnable() { Instantiate(PlayerPref, new Vector3(transform.position.x, transform.position.y, transform.position.z), Quaternion.identity); }
Thats exactly how I spawn the player in the first place, but when it dies the same coroutine doesen't want to run again.
well i dont know then...
i have a prefab model and one gameobject to my scene i attach a spawner script to the gameobject in which i pass the prefab from the inspector and it spawns the prefab many times without a problem
spawns yes, it wont respawn, try to spawn object with coroutine, then destroy it and respawn again with coroutine, like in my code, I am starting to think it some sort of bag.
i have a simple tower defense game where i spawn creeps and they die from a turrent but they still get spawned on next wave and i do that with a co-routine
If try to run this part of code thru a coroutine it wipes the error, but the respawn coroutine doesent run.
public IEnumerator 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);
}
yeild return null;
}
Your "TakeDamageFormEnemy" coroutine is not a coroutine as it doesn't have any yield statement. So if you have code that actually compiles, where did you place the yield statement? Since you said the error goes away but the coroutine doesn't work i have a strong feeling that your "spawn" does in deed get deactivated somewhere. Have you tried putting a Debug.Log inside OnEnable / OnDisable of your spawn script? does any of those get fired when your player dies?
Answer by Fragmental · Mar 13, 2017 at 12:15 PM
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.
Also if I add the "spawnScript" to a "PlayerPref" in Inspector, it gives the same error that objec isn't active and coroutine can not be started, but if I readd "spawnScript" to the "Player" in a scene everything start working. It seams like Prefabs and a scene is not conected to each other even if I refresh all prefabs in a scene.
Solution is to make it like this but don't understand why it wont taking the info from prefab.
spawn = GameObject.Find("SpawnPoint").GetComponent<PlayerSpawnScript>();
spawn.PlayerRespawnIfDead();
Yeap I tested it some more you can't start a respawn coroutine in child object, it has to be parent the everything goin to work perfect.
One thing I had an issue with recently was execution order. Some code would execute before other code I needed, and it would cause null reference errors, even when it shouldn't have. Drove me nuts. I don't know why the coroutine being in a child object would make a difference, as long as all the parents were active, unless it was an execution order issue.
I fixed those issues by making my functions coroutines and dropping in a well placed yield return null;
In your case it might look something like this, if the coroutine wasn't able to launch or finish in time before it's parent game object got destroyed.
public IEnumerator TakeDamageFormEnemy(float dmg)
{
CurHpLvl = CurHpLvl - (int)(dmg - PlayerStats.CharArmor);
if (CurHpLvl <= 0)
{
// Initiate dead of the Player
Debug.Log("Player is dead");
Debug.Log("spawn is active: "+ spawn.activeInHierarchy);
StartCoroutine(spawn.RespawnAfterDeadCorutine());
Debug.Log("spawn is active: "+ spawn.activeInHierarchy);
yield return null;
Destroy(gameObject);
}
}
edit: Alternatively
yield return StartCoroutine(spawn.RespawnAfterDeadCorutine());
will wait until the Coroutine finishes before continuing to the next line.
Glad you got it working.
Answer by IgorAherne · Mar 12, 2017 at 12:30 PM
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
1) 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".
2) 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.
3) 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.
4) 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.
5) 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:
Coroutine myCoroutineReference = myAlienComponentReference.StartCoroutine( myLocalyDefinedOne() )
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
Answer by Bren0831 · Mar 13, 2017 at 06:54 AM
In line 9 of the player script what gameObject are you destroying?
Player object starts a coroutine on empty gameobject "spawn" then gets destroyed. Then in "spawn" hapens this:
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;
}
And returns the error "spawn" is inactive.
How is the variable spawn
in spawn.StartCoroutine(spawn.RespawnAfterDeadCorutine());
being assigned?
I assign the spawn Script through the Inspector. In class it looks like this public PlayerSpawnScript spawn;
public void PlayerRespawnIfDead()
{
// Респаун игрока если был убит мобами
Debug.Log("SpawnScript and object is active " + gameObject.activeInHierarchy);
StartCoroutine(RespawnAfterDeadCorutine());
}
public IEnumerator RespawnAfterDeadCorutine()
{
yield return new WaitForSeconds(PlayerRespawn);
Debug.Log("RespawnCorrutine is worked out");
Instantiate(PlayerPref, new Vector3(spawnPoint.position.x, spawnPoint.position.y, spawnPoint.position.z), Quaternion.identity);
yield return null;
}
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.
If it is an weird activity problem try creating an empty gameobject, all alone (no parent, nor children), and ins$$anonymous$$d of creating a public PlayerScriptSpawn spawn
use a private one and set it to GameObject.Find ("Spawn").GetComponent (). Perhaphs beaing more straight foward helps unity a little bit.
Answer by Matt1000 · Mar 12, 2017 at 02:58 PM
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*/);
}
}
Answer by SnStarr · Mar 13, 2017 at 07:30 AM
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.
Actually the coroutine is not in the player gameobject, its in an empty sapwn GO. That's why she calls spawner.StartCoroutine ()
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Can't start Coroutine since object is "Inactive" 1 Answer
Multiple Cars not working 1 Answer
Error Coroutine couldn't be started! 3 Answers
Fade In / Out not working C# 1 Answer