Maurice Bekambo
Maurice Bekambo

Reputation: 325

Changing color of text for specific amount of time in C# and Unity

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

Answers (3)

derHugo
derHugo

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 using MonoBehaviour.StopCoroutine and MonoBehaviour.StopAllCoroutines. Coroutines are also stopped when the MonoBehaviour is destroyed.

Upvotes: 3

Jichael
Jichael

Reputation: 820

You have to use a Coroutinefor 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

caxapexac
caxapexac

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

Related Questions