- 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