Gets stuck on WaitForSeconds

I’m having a problem with Coroutines and yield. When the ball passes the goal lines the score updates and then a new ball i supposed to be spawned after 1.5 sec. But I get stuck on yield return new WaitForSeconds(1.5f); in Pong.cs. I’ve read the docs but I can still not figure out whats the problem.

The score is added but no ball is spawned.

Updates:

  • If I comment out yield return new
    WaitForSeconds(1.5f);
    the code
    works, but of course doesn’t wait.
  • I’m new to Unity and C# so don’t trust my code as it was your own :slight_smile:

Ball.cs attached to BallPrefab

using UnityEngine;
using System.Collections;

public class Ball : MonoBehaviour {
	
	private static int TOP, BOT;
	private static Pong PONG;
	
	public float maxVelocity = 3;
    public float minVelocity = 0.1f;
	
	void Awake () {
		PONG = Pong.INSTANCE;
		TOP = ((int)Pong.TOP.z) + 2;
		BOT = ((int)Pong.BOT.z) - 2;
		rigidbody.velocity = new Vector3(0, 0, -7);
	}
	
	// Update is called once per frame
	void Update () {
		
		//Make sure we stay between the MAX and MIN speed.
        float totalVelocity = Vector3.Magnitude(rigidbody.velocity);
        if(totalVelocity>maxVelocity) {
            float tooHard = totalVelocity / maxVelocity;
            rigidbody.velocity /= tooHard;
        } else if (totalVelocity < minVelocity) {
            float tooSlowRate = totalVelocity / minVelocity;
            rigidbody.velocity /= tooSlowRate;
        }
		
		if(transform.position.z <= BOT) {
			Destroy(gameObject);
			StartCoroutine(PONG.Goal(1));
		} else if(transform.position.z >= TOP) {
			Destroy(gameObject);
			StartCoroutine(PONG.Goal(2));
		}
	}
}

Pong.cs attached to MainCamera

using UnityEngine;
using System.Collections;
using System.Threading;
using System.Diagnostics;

public enum PongGameState { playing, won, lost };

public class Pong : MonoBehaviour {
	
	public Transform ballPrefab;
	public static Pong INSTANCE;
	
	public static Vector3 TOP = new Vector3(10, 0, 15);
	public static Vector3 BOT = new Vector3(10, 0, 5);
	public static Vector3 LEFT = new Vector3(5, 0, 10);
	public static Vector3 RIGHT = new Vector3(15, 0, 10);
	
	private PongGameState gameState;
	
	void Awake() {
		INSTANCE = this;
        gameState = PongGameState.playing;
        Time.timeScale = 1.0f;
        SpawnBall();
    }
	
    private void SpawnBall() {
		print("spawnball");
        Instantiate(ballPrefab, new Vector3(10.0f, 0.0f, 10.0f), Quaternion.identity);
    }
	
	public IEnumerator Goal(int player){
		print("in goal");
		Scores.AddPoint(player);
		yield return new WaitForSeconds(1.5f);
        print("in goal");
		SpawnBall();
	}
}

You’re destroying the object which starts the coroutine, stopping it from running after the wait

Change this line (both times):

StartCoroutine(PONG.Goal(1));

to

PONG.StartCoroutine(PONG.Goal(1));

So that the coroutine is run on the same object it’s interested in

Edit, to make it more obvious why:

When you start a coroutine, the monobehaviour it’s run from is “attached” to it in a way that when the monobehaviour is disabled or destroyed, the coroutine will stop running

Try making Goal() return SpawnBall().

EDIT: Also check this post form more information.