Reputation: 15
My code:
public class Enemy : MonoBehaviour
{
public GameObject deathEffect;
public float health = 4f;
public static int EnemiesAlive = 0;
public int loadToScene;
void Start ()
{
EnemiesAlive++;
}
void OnCollisionEnter2D (Collision2D colInfo)
{
if (colInfo.relativeVelocity.magnitude > health)
{
Die();
}
}
void Die ()
{
Instantiate(deathEffect, transform.position, Quaternion.identity);
EnemiesAlive--;
if (EnemiesAlive <= 0)
{
Debug.Log ("LEVEL WON!");
Invoke("ChangeScene",2f);
}
Destroy(gameObject);
}
void ChangeScene()
{
Debug.Log ("Hello");
loadToScene = 1;
SceneManager.LoadScene (loadToScene);
}
}
Can anyone point me out why Invoke()
does not work? I wanted to add 2 seconds delay before changing scene once the condition (EnemiesAlive <= 0)
is fulfilled. Debug.Log ("LEVEL WON!");
is outputted while Debug.Log ("Hello");
is not. I know I can use StartCoroutine
also but I wanted to use Invoke()
instead.
Upvotes: 1
Views: 221
Reputation: 125275
That's because you are calling the Destroy(gameObject) like m.rogalski mentioned and it does not have a chance of executing Invoke("ChangeScene",2f);
.
However, I have a feeling that you want to destroy that Object right away without waiting because you want stuff(such as OnCollisionEnter2D
) in that script to stop running but at the-same time want to load your scene later on.
If this is the case then you have to put the loading function in a separate script attached to a separate GameObject. This script will not destroy when you call Destroy(gameObject)
.
1.Create a new GameObject called "SceneLdObj".
2.Attach the script below to the "SceneLdObj" GameObject.
public class SceneLoader : MonoBehaviour
{
int loadToScene = 1;
public void ChangeScene(int sceneLevel)
{
loadToScene = sceneLevel;
Invoke("loadScene", 2f);
}
private void loadScene()
{
SceneManager.LoadScene(loadToScene);
}
}
Add the script below to the script in your question:
SceneLoader sceneLoader;
void Start()
{
sceneLoader = GameObject.Find("SceneLdObj").GetComponent<SceneLoader>();
}
Now, you can the load function from your Die function and it will still work even though the GameObject is already destroyed.
void Die()
{
Instantiate(deathEffect, transform.position, Quaternion.identity);
EnemiesAlive--;
if (EnemiesAlive <= 0)
{
Debug.Log("LEVEL WON!");
//Call that function from another script
sceneLoader.ChangeScene(1);
}
Destroy(gameObject);
}
EDIT:
This should be your new Enemy
script:
public class Enemy : MonoBehaviour
{
public GameObject deathEffect;
public float health = 4f;
public static int EnemiesAlive = 0;
public int loadToScene;
SceneLoader sceneLoader;
void Start ()
{
sceneLoader = GameObject.Find("SceneLdObj").GetComponent<SceneLoader>();
EnemiesAlive++;
}
void OnCollisionEnter2D (Collision2D colInfo)
{
if (colInfo.relativeVelocity.magnitude > health)
{
Die();
}
}
void Die ()
{
Instantiate(deathEffect, transform.position, Quaternion.identity);
EnemiesAlive--;
if (EnemiesAlive <= 0)
{
Debug.Log ("LEVEL WON!");
//Call that function from another script
sceneLoader.ChangeScene(1);
}
Destroy(gameObject);
}
void ChangeScene()
{
Debug.Log ("Hello");
loadToScene = 1;
SceneManager.LoadScene (loadToScene);
}
}
Upvotes: 1
Reputation: 5920
The problem is that Invoke
is in fact getting called but your object is destroyed before invoked method executes.
To fix that, move Destroy(gameObject)
to the ChangeScene
method :
void Die ()
{
Instantiate(deathEffect, transform.position, Quaternion.identity);
EnemiesAlive--;
if (EnemiesAlive <= 0)
{
Debug.Log ("LEVEL WON!");
Invoke("ChangeScene",2f);
}
}
void ChangeScene()
{
Debug.Log ("Hello");
loadToScene = 1;
Destroy(gameObject);
SceneManager.LoadScene (loadToScene);
}
You can optionally specify the time after which the object will be destroyed using an overload of Destroy
method : Destroy(gameObject, 1.0f)
( will destroy object after one second ).
Upvotes: 2