I keep seeing people posting loading scenes where the progress bar works. I've got an animated character while the scene loads, and it all just freezes. Like people have said it's not perfectly async. The debug goes from 0 to 0.9 and you can see the delay in the timestamp. So, I thought maybe if I animated using code rather than the animator and ran that code on a new thread it might keep animating but alas that didn't work. unity gave an error saying I couldn't use threading that way I think it has something to do with accessing the image sprite. This is the error
UnityException: get_rect 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.
EDIT Question: Is there any way of updating a sprite in another thread or is the other thread only good for calculations and cant update the scene at all. (only time I've used multithreading was to calculate pathfinding but it sent the calculated path back to the main thread to be executed)
private void Start()
{
animating = true;
backGroundThread = new Thread(AnimateIt);
backGroundThread.Start();
StartCoroutine(LoadScene());
}
private void OnDestroy()
{
animating = false;
}
IEnumerator LoadScene()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(gotoScene.ToString(), LoadSceneMode.Single);
asyncLoad.allowSceneActivation = false;
while (!asyncLoad.isDone)
{
Debug.Log(asyncLoad.progress);
if (asyncLoad.progress >= 0.9f)
{
yield return new WaitForSeconds(0.5f);
asyncLoad.allowSceneActivation = true;
}
yield return null;
}
yield return null;
Debug.Log("Out Of Loops");
Destroy(gameObject);
}
public void AnimateIt()
{
int currentFrame = 0;
while (animating)
{
int frame = (int)(currentFrame % frameList.Count);
frameSprite.sprite = frameList[frame];
currentFrame++;
Thread.Sleep((int)((frameRate / 60)*1000));
}
}
EDIT------ The original is super simple. Its just a load and the animation is just done on an animator. You can see in the video that the animation on the animator freezes. You can see that the while loop doesnt seem to loop properly. It goes from 0 - 0.9 after 7 seconds without doing any sort of loop to show the progress
Here are the video and the code Youtube video
public void SetUp(LOCATIONS _gotoScene)
{
gotoScene = _gotoScene;
DontDestroyOnLoad(gameObject);
}
void FadeOnfinished()
{
StartCoroutine(LoadScene());
}
IEnumerator LoadScene()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(gotoScene.ToString(), LoadSceneMode.Single);
asyncLoad.allowSceneActivation = false;
Debug.Log("Going to Load");
while (!asyncLoad.isDone)
{
Debug.Log("Loading: "+ asyncLoad.progress * 100 + "%");
if (asyncLoad.progress >= 0.9f)
{
yield return new WaitForSeconds(0.5f);
asyncLoad.allowSceneActivation = true;
}
yield return null;
}
yield return null;
Debug.Log("Loaded");
animator.SetTrigger("Off");
}
EDIT Question: Is there any way of updating a sprite in another thread or is the other thread only good for calculations and cant update the scene at allmost of Unity API in particular anything accessing or setting things in the native c++ Engine (basically anything that affects the scene directly) can only be done on the main thread. There are certain exceptions like the Mesh API, Compute Shaders, and certain Image/Texture API .. but unless there is a specific explicit async support from Unity most of the time the answer is no, it needs to be the main threadAwakeandStartmethods also initialize all the physics and colliders etc .. this all happens in the main thread .. you should profile where the freeze comes from and once you figured out what actually causes the freeze you could workaround it (e.g. enable objects one by one in a Coroutine or similar while staying on the loading screen)