- 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