2
\$\begingroup\$

I need to delay the load new level by a few second. Please help.This is the script I need to use:

void OnCollisionEnter2D(Collision2D col)
{
    if (col.gameObject.tag == "Enemy")
    {
         score = score + 50;
         Destroy (gameObject);
         /*Here I need to wait for 3 sec then it should load the next level*/
         SceneManager.LoadScene(nextLevel);
    }
}

I have tried this code but this doesn't update my score and don't wait and don't even load the next level:

void OnCollisionEnter2D(Collision2D col)
{
    Debug.Log ("Collision");
    if (col.gameObject.tag == "Enemy")
    {        
        score = score + 50;
        Destroy (gameObject);
        StartCoroutine (WaitForIt (3.0F)); 
    }
}

IEnumerator WaitForIt(float waitTime)
{
    yield return new WaitForSeconds(waitTime);
    SceneManager.LoadScene(nextLevel);
}
\$\endgroup\$

3 Answers 3

5
\$\begingroup\$

You are destroying the GameObject on which this script is running as soon as it collides with an enemy. (Destroy (gameObject);)

That means it can't wait 3 seconds before loading the next scene - in 3 seconds' time, it will no longer exist and so it can't run any scripts at all!

You'll want to either delay the object's destruction until after the delay, or move the delay logic into a script you don't destroy (like a game state manager of some kind)

Edit: here's an example...

We can put a ScoreManager somewhere else in our scene, on an object we don't plan to destroy:

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

public class ScoreManager : MonoBehaviour
{
     // This lets other scripts in the scene find this single instance without searching.
     static ScoreManager _instance;
     public ScoreManager GetInstance() { return _instance; }

     // Inspector variables so we can view our score, and configure scene loading.
     public int score;
     public string nextSceneName;
     public float waitTime;

     // Ensure the instance is ready by the time it's needed.
     void Awake()
     {
         _instance = this;
     }

     // This replaces the work that the ball was doing previously.
     public void ScorePointsAndEndScene(int pointsScored)
     {
         score += pointsScored;
         StartCoroutine(WaitAndLoadScene());
     }

     IEnumerator WaitAndLoadScene()
     {
         yield return new WaitForSeconds(waitTime);
         SceneManager.LoadScene(nextSceneName);
     }
}

Now your ball script can just worry about destroying itself, leaving the score & scene management to your other script:

void OnCollisionEnter2D(Collision2D col)
{
    Debug.Log ("Collision");
    if (col.gameObject.CompareTag("Enemy"))
    {   
        ScoreManager.GetInstance().ScorePointsAndEndScene(20);
        Destroy(gameObject);        
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your reply, I have two balls which I want to put in the basket, once the balls touch the basket it should disappear and my score should increase and wait for 3 sec then it should load the next level. If I dont destroy the gameobject then how can I disappear the balls?First bloack of code, my score is increaing and i am able to move to the next level hoever it does not wait for 3 sec. I am totally new at unity. So please dont mind :) \$\endgroup\$ Jun 29, 2016 at 7:07
  • \$\begingroup\$ If you want to destroy the object, then as I said above you need to do your waiting somewhere else, on an object that you're not going to destroy. I've added an example of what this might look like. \$\endgroup\$
    – DMGregory
    Jun 29, 2016 at 12:29
-1
\$\begingroup\$

I suggest you use Invoke. It's pretty simple, and the documentation is pretty clear, too.

http://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Unfortunately Invoked methods don't survive the destruction of the object they're attached to, just like the Coroutines the user is currently using. \$\endgroup\$
    – DMGregory
    Jun 29, 2016 at 2:39
  • \$\begingroup\$ use a GameManager object that gets notified when level is finished, then delay for 3 sec and then loads the new levels. \$\endgroup\$ Jun 29, 2016 at 7:43
  • 1
    \$\begingroup\$ Hi @DanielNetzer, can you show me a example how to use a GameManager? Please do not mind. I am totally new and I am struggling for last 4 days. Thanks. \$\endgroup\$ Jun 29, 2016 at 9:30
  • \$\begingroup\$ look at @DMGregory answer, its the same idea he just called it SceneManager. in general when you code a general concept that you want to recycle such as changing levels, or saving scores in between scenes you should have an empty game object that WONT be destroyed when you start a new scene and in that object you attach a script to hold all the variables you want and to manipulate those variables. tl;dr check the answer above. \$\endgroup\$ Jun 29, 2016 at 14:50
-1
\$\begingroup\$

I have solution in how to delay 3 second after reload level but I dont try to have a score here: You must have an object which has collision with your main Object Ex: Obstacle and main Object is Rocket(tag:Player) This script is link to Obstacle (3f is 3s) enter image description here then this is script is link to Rocket enter image description here

\$\endgroup\$
1
  • 4
    \$\begingroup\$ Please share code as text, not as images. Text is better at attracting search hits to bring readers to your answer, and is more accessible to screen readers and translation software, so more folks can learn from what you're sharing. It also makes it easier to copy & paste example code to test it out. \$\endgroup\$
    – DMGregory
    Aug 21, 2022 at 12:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .