quickstart-unity: Main thread errors and freezing on Android - Unity 2018.1.7f1, Firebase SDK 5.1.1, IL2CPP, .NET 4.x, Windows 10 x64

Unity Upgrade

I’ve recently upgrade from Unity 2017.3.0f3 because I started getting freezes on Android when I call anything from the Firebase SDK. The version of Unity I have now is 2018.1.7f1. I am also using the latest firebase sdk 5.1.1.

.NET Upgrade and IL2CPP

Still not getting the game running on android (editor works fine), I switched to IL2CPP and .NET 4.x. As far as I can tell, these technologies are compatible with the Firebase SDK as long as use the correct Parse SDK dlls. See bottom of this page.

Editor Errors

Now, I’m getting the following error when I try run the game in the editor (Android is also still broken): get_isActiveAndEnabled can only be called from the main thread. The stack trace points to a simple line of code that, if I delete it, it just throws a similar error somewhere else (code that always worked prior to Firebase): get_gameObject can only be called from the main thread.

The Issue

Finally, I tested disabling my firebase sdk. This resulted in the game running smoothly in the editor and on an Android device.

The errors also make it quite clear that Unity can’t handle code called from multiple threads. I’ve also seen this from other issues people are experiencing. I also believe this is why the Android game on Unity 2017 didn’t exactly crash, it just froze (probably switching to a different thread once Firebase SDK is used). And it only happened occasionally, not every time (perhaps there aren’t always other threads available). I’m also not sure whether this issue started with Firebase Authentication or Realtime Database (I’m assuming both because they both use System.Threading).

Anyway…

  • Is this a known issue people are experiencing? How did you fix it?
  • Is there perhaps a older SDK/Unity version that fixes this? If so, please share your versions.
  • Is there a trick to put all the Firebase SDK calls on the main thread even if it uses System.Theading.Task to run the calls asynchronously?
  • Perhaps I’m using the Firebase SDK incorrectly? Here is an snippet from one of my functions:
if (auth.CurrentUser.IsAnonymous) {
	Task<DataSnapshot> dbGetUser = DBGetUser();
	dbGetUser.ContinueWith(tGetUser => {
			if (tGetUser.IsCanceled || tGetUser.IsFaulted || !tGetUser.IsCompleted) {
			return;
			}
			if (tGetUser.Result == null || tGetUser.Result.GetRawJsonValue() == null) {
			Task dbNewUser = DBNewUser(true);
			dbNewUser.ContinueWith(tNewUser => {
					if (tNewUser.IsCanceled || tNewUser.IsFaulted || !tNewUser.IsCompleted) {
					return;
					}
					Task<DataSnapshot> dbGetNewUser = DBGetUser();
					dbGetNewUser.ContinueWith(tGetNewUser => {
							if (tGetNewUser.IsCanceled || tGetNewUser.IsFaulted || !tGetNewUser.IsCompleted) {
							return;
							}
							PrepareGame("Anonymous", JsonUtility.FromJson<User>(tGetNewUser.Result.GetRawJsonValue()));
							});
					});
			} else {
				PrepareGame("Anonymous", JsonUtility.FromJson<User>(tGetUser.Result.GetRawJsonValue()));
			}
	});
}

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 28 (12 by maintainers)

Most upvoted comments

@fanus

I’ve been trying to reproduce this using Unity TestApp but unable to make Android build crash.

I was trying to use exactly the same environment.

  • Unity 2018.1.7f1
  • Firebase SDK 5.1.1
  • IL2CPP
  • .NET 4.x
  • Windows 10 x64
  • Target API Level 25 (7.1 Nouget)
  • C++ Configuration Level - Debug
  • Disable HW Statistics
  • Call FirebaseApp.CheckAndFixDependenciesAsync() in Awake()
  • Use TaskScheduler.FromCurrentSynchronizationContext() with ContinueWith()

Also, I was using Pixel phone with Android 8.0.0 for testing. I don’t think the device matter but which phone where you using?

Also, could you try to simplify your code to FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>{}, TaskScheduler.FromCurrentSynchronizationContext() );

And you can try the TestApp as well. If it crash, could you provide more log data?

Thank you!

Hi Fanus,

When you are using Task.ContinueWith(continuationFunc) in Unity with .NET 4.x, the continuation function will NOT be called from the main thread. This behavior is different from Unity with .NET 3.x, where continuation function is always called from the main thread. Therefore, if you are accessing any GameObject or its properties in the continuation function, ex. PrepareGame(), Unity will definitely complain about “xxxx can only be called from the main thread”, and this may result in unexpected behavior.

One quick solution to this problem, with minimum code change, is to use Task.ContinueWith(continuationFunc, scheduler) with TaskScheduler.FromCurrentSynchronizationContext(), assuming your first ContinueWith() is called from the main thread. If not, you will need to store a reference of the scheduler from the main thread. Here are some references: https://msdn.microsoft.com/en-us/library/dd321428(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.fromcurrentsynchronizationcontext(v=vs.110).aspx https://stackoverflow.com/questions/4331262/task-continuation-on-ui-thread

Another option for you is to use await instead of ContinueWith(). This also makes your code prettier. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

What I am curious about is the configuration when you first started getting freeze on Android. May I know the Unity version, Firebase SDK version and .NET version you were using? It would be awesome if you have any additional information!

Thank you and hope this information helps.

Shawn