Reputation: 325
I'm currently working on a game in Unity and I have a small problem. I'm trying to create an effect where the color of the ingame score counter temporarily changes color when the score counter gets incremented and then switches back to it's original color. However when I attempt to do this my game keeps on crashing. I'm using a while loop in order to preform this task but as soon as I try to trigger this event in game my game aswell as Unity crash. Does anyone know why this happens and maybe have a solution in order to solve this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StarCollision : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "White Ball" )
{
gameObject.SetActive(false);
ScoreScript.scoreValue += 1;
while (Time.deltaTime < 0.2f)
{
ScoreScript.score.color = Color.yellow;
}
ScoreScript.score.color = Color.white;
}
}
}
Upvotes: 1
Views: 1545
Reputation: 90749
Your while
loop is blocking the Main/UI thread => it is executed and the next frame only rendered after it finished!
Additionally Time.deltaTime
is the time passed since the last frame was rendered ... so it might never reach 0.2
since assuming you run at 60 fps
it's value will be about 0.017
=> Unity freezes!
You should use a Coroutine instead:
public class StarCollision : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "White Ball" )
{
ScoreScript.scoreValue += 1;
// start the routine
StartCoroutine(ChangeColor());
gameObject.SetActive(false);
}
}
private IEnumerator ChangeColor()
{
ScoreScript.score.color = Color.yellow;
// yield says: return to main thread, renderer the frame
// and continue from here in the next frame
// WaitForseconds .. does exactly this
yield return new WaitForseconds(0.2f);
ScoreScript.score.color = Color.white;
}
}
I would leave your gameObject.SetActive(false);
before the Coroutine finished but after it started since you want it immediately and
Note: Coroutines are not stopped when a
MonoBehaviour
is disabled, but only when it is definitely destroyed. You can stop a Coroutine usingMonoBehaviour.StopCoroutine
andMonoBehaviour.StopAllCoroutines
. Coroutines are also stopped when theMonoBehaviour
is destroyed.
Upvotes: 3
Reputation: 820
You have to use a Coroutine
for that. Check out https://docs.unity3d.com/Manual/Coroutines.html
Basically you just yield one frame at each iteration of the loop, for the amount of time you want, or you yield for a specific amount of time.
Hope it helped
Upvotes: -1
Reputation: 914
Use Coroutines and its WaitForSeconds method
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StarCollision : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("White Ball"))
{
ScoreScript.scoreValue += 1;
StartCoroutine(ChangeColor());
}
}
private IEnumerator ChangeColor ()
{
ScoreScript.score.color = Color.yellow;
yield return new WaitForSeconds(0.2f);
ScoreScript.score.color = Color.white;
gameObject.SetActive(false);
}
}
Upvotes: 3