- Home /
Game freezes everything when calling WaitForSeconds
I am working on a Dice Game, where 5 players can play on turn bases. Currently, I have written the following code, it sometimes works but producing StackOverflow Exception in "CountDown.OnCountingFinished()" and most of the time, everything just freezes including Unity Editor.
Problem is occurring when StartCoroutine(PlayAsABot())
is called for second time. The statement Debug.Log("Waiting over: Selecting Dice")
is never called and everything just freezes, can't stop, can't close.
Seat.cs
public class Seat : MonoBehaviour {
public Image EmptyImage;
public Image PlayerImage;
public GameObject PlayerContainer;
public CountDown Timer;
public Text Title;
public Text Chips;
public RectTransform Bet;
public GameObject InviteButton;
public RectTransform DealerPosition;
public bool isForMainPlayer = false;
public int Index;
public bool IsOccupied;
public Player Player;
public bool havePlayed = false;
public bool isMyTurn = false;
public bool isOnHold = false;
public bool isOnWatch = false;
public bool isBot = false;
public int[] diceSelection = new int[3];
public int totalBetPlaced = 0;
public void AssignPlayer(Player player, float timeOut=15f){
Player = player;
IsOccupied = true;
EmptyImage.enabled = false;
if (!isForMainPlayer) {
Title.text = player.Name;
InviteButton.SetActive (false);
}
Timer.timeOut = timeOut;
Chips.text = "Rs." + player.Chips;
PlayerContainer.SetActive (true);
PlayerImage.sprite = player.Image.sprite;
}
public void Play(){
isOnWatch = false;
isOnHold = false;
isMyTurn = true;
Timer.StartCountDown ();
if (isBot) {
float waitForSeconds = Random.Range (2f, 10f);
StartCoroutine (PlayAsABot (waitForSeconds));
}
if (isForMainPlayer) {
StartCoroutine (PlayAsABot (1));
playerCallback.OnPlayerDonePlaying(Index);
}
}
public void Hold(){
isOnHold = true;
}
public void Watch(){
isOnWatch = true;
}
private bool isCollectingBet = false;
public void SubmitBooty(int value){
Player.Chips -= value;
totalBetPlaced += value;
Bet.GetComponent<Text>().text = "Rs. " + value;
Bet.gameObject.SetActive(true);
isCollectingBet = true;
}
private Vector3 betInitPos;
void Start(){
betInitPos = Bet.position;
}
void Update(){
if (isCollectingBet) {
StartCoroutine (CollectBet ());
}
}
IEnumerator CollectBet(){
Bet.position = Vector3.MoveTowards (Bet.position, DealerPosition.position, 300.0f * Time.deltaTime);
float distance = Vector3.Distance (Bet.position, DealerPosition.position);
if (distance <= 0.5f) {
Bet.gameObject.SetActive(false);
Bet.position = betInitPos;
isCollectingBet = false;
}
yield return null;
}
private PlayerCallback playerCallback;
public void SetPlayerCallback(PlayerCallback callback){
playerCallback = callback;
}
IEnumerator PlayAsABot(float wait){
Debug.Log("Waiting for: " + wait);
yield return new WaitForSeconds(wait);
Debug.Log("Waiting over: Selecting Dice");
SelectDice ();
Debug.Log ("Selecting Dice: Dice Selected");
SubmitBooty(Random.Range(100, 400));
Timer.OnCountingFinished ();
isMyTurn = false;
havePlayed = true;
print ("Ok: " + Player.name);
playerCallback.OnPlayerDonePlaying (Index);
yield return null;
}
void SelectDice(){
diceSelection [0] = 1;
diceSelection [1] = 2;
diceSelection [2] = 3;
print ("Selection By: Player " + Player.name);
foreach (int d in diceSelection) {
print (d + "");
}
}
}
CountDown.cs
public class CountDown : MonoBehaviour {
public Image countDownImage;
public float timeOut = 15f;
public float time;
public bool isCounting = false;
Color defaultColor;
Color lerpedColor;
// Use this for initialization
void Start () {
countDownImage = GetComponent<Image> ();
defaultColor = countDownImage.color;
lerpedColor = defaultColor;
time = timeOut;
StartCountDown ();
}
// Update is called once per frame
void Update () {
if (isCounting) {
if (time > 0) {
time -= Time.deltaTime;
if ((time / timeOut) < 0.5f) {
lerpedColor = Color.Lerp (Color.red, defaultColor, Mathf.PingPong (Time.time, 1));
}
countDownImage.color = lerpedColor;
countDownImage.fillAmount = time/timeOut;
if (time <= 0) {
OnCountingFinished ();
}
}
}
}
public void StartCountDown(){
isCounting = true;
gameObject.SetActive (true);
}
public void OnCountingFinished(){
gameObject.SetActive (false);
isCounting = false;
time = timeOut;
lerpedColor = defaultColor;
countDownImage.color = defaultColor;
countDownImage.fillAmount = 1f;
}
}
Answer by thezeeshantariq · Feb 23, 2020 at 12:13 PM
Ok, I found the main problem which was causing the Freeze.
The StackOverFlow exception was occurring, as I have called
Time.OnCountingFinished()
twice from other scripts as well.The Freeze was occurring due to Line 60 where I was calling
playerCallback.OnPlayerDonePlaying()
right after starting the coroutine. This line was forcing the currentgameobject
to abandon everything and move on. RemovingplayerCallback.OnPlayerDonePlaying()
solved everything.