- Home /
 
C# timers - SetSprite_INTERNAL can only be called from the main thread.
So I'm having some issues with setting sprites using timers in C#/unity, here is my script http://pastie.org/8736350
Now the countdown itself works. The issue is that it doesn't want to change the sprite and gives me the following error:
SetSprite_INTERNAL can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
Does this means it wants me to move:
     countdown.Interval = 1000;
     countdown.Elapsed += new ElapsedEventHandler(timerproc);
     countdown.Enabled = true;
 
               Under Start()? Cause I do not want that. I want the timer only to run once and then I want to Stop() it. Why is this ElapsedEventHandler running in a different thread?
I don't understand and if someone could explain that would be greatly appriciated.
Answer by whydoidoit · Feb 15, 2014 at 03:31 PM
Timers is using another thread - you have two choices:
Sync your calls to the main thread by sticking them in a delegate that gets called from an Update or Coroutine
Use a coroutine for this, it's what they are good at!
Code:
 using UnityEngine;
 using System.Collections;
 
 public class CountDown : MonoBehaviour 
 {
     public Sprite countdownThree;
     public Sprite countdownTwo;
     public Sprite countdownOne;
     public Sprite countdownGo;
     SpriteRenderer countdownNumber;
     
     int countdownTime = 5;
 
     void Start () 
     {
         countdownNumber = gameObject.GetComponent<SpriteRenderer>();
         countdownNumber.sprite = null;
     }
 
     void Update () 
     {
         if(Input.GetKeyDown ("x"))
         {
             StartCoroutine(StartCountDown());
         }
     }
 
     public IEnumerator StartCountDown()
     {
         countdownNumber.enabled = true;
         countdownNumber.sprite = countdownThree;
         yield return new WaitForSeconds(1);
         countdownNumber.sprite = countdownTwo;
         yield return new WaitForSeconds(1);
         countdownNumber.sprite = countdownOne;
         yield return new WaitForSeconds(1);
         countdownNumber.sprite = countdownGo;
         yield return new WaitForSeconds(1);
         countdownNumber.enabled = false;
     }
 
   
 
 }
 
              Or probably more flexible:
 using UnityEngine;
 using System.Collections;
  
 public class CountDown : $$anonymous$$onoBehaviour 
 {
     public Sprite[] countDownSprites;
     SpriteRenderer countdownNumber;
  
  
     void Start () 
     {
        countdownNumber = gameObject.GetComponent<SpriteRenderer>();
        countdownNumber.sprite = null;
     }
  
     void Update () 
     {
        if(Input.Get$$anonymous$$eyDown ("x"))
        {
          StartCoroutine(StartCountDown());
        }
     }
  
     public IEnumerator StartCountDown()
     {
         countdownNumber.enabled = true;
         for(var i = 0; i < countDownSprites.Length; i++) {
             countdownNumber.sprite = countDownSprites[i];
             yield return new WaitForSeconds(1);
         }
         countdownNumber.enabled = false;
  
     }
  
  
  
 }
     
 
                 Thank you both, I will look into this and try to understand the code.
@whydoidoit I am getting this error with your code: Assets/Scripts/Level 1/CountDown.cs(47,53): error CS1061: Type UnityEngine.Sprite[]' does not contain a definition for length' and no extension method length' of type UnityEngine.Sprite[]' could be found (are you missing a using directive or an assembly reference?)  Edit: It's suppose to be Lenght not lenght :) 
Your answer
 
             Follow this Question
Related Questions
Flip Sprite C# 0 Answers
Multiple Cars not working 1 Answer
WhY the exact same object behaves different ? 0 Answers
Using Texture Assets in Code 1 Answer
How do I make sprite renderer's sprite change in runtime c#? 0 Answers