1
\$\begingroup\$

In my project I am trying to build a dedicated server build to deploy to Multiplay hosting services.

Build target is Linux OS,build settings are default, scripting backend set to IL2CPP.

When Addressables.InstantiateAsync() is being called for the first time, or when Resources.Load() gets called, a "Graphics device is null" error is fired and the server crashes. Here are the logs: When using Addressables.InstantiateAsync().WaitForCompletion() :

Graphics device is null.
UnityEngine.ResourceManagement.ResourceProviders.AssetBundleResource:GetAssetBundle()
UnityEngine.ResourceManagement.ResourceProviders.AssetBundleResource:WaitForCompletionHandler()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.GroupOperation:InvokeWaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.ProviderOperation`1:InvokeWaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1:WaitForCompletion()
UnityEngine.ResourceManagement.InstanceOperation:InvokeWaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:WaitForCompletion()
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1:WaitForCompletion()
<OnAllocate>d__5:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.Tasks.AwaitTaskContinuation:RunOrScheduleAction(Action, Boolean, Task&)
System.Threading.Tasks.Task:FinishContinuations()
System.Threading.Tasks.Task`1:TrySetResult(TResult)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(TResult)
Unity.Services.Multiplay.Internal.<GetPayloadAllocationAsPlainText>d__9:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.Tasks.AwaitTaskContinuation:RunOrScheduleAction(Action, Boolean, Task&)
System.Threading.Tasks.Task:FinishContinuations()
System.Threading.Tasks.Task`1:TrySetResult(TResult)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(TResult)
Unity.Services.Multiplay.Apis.Payload.<PayloadAllocationAsync>d__7:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.Tasks.AwaitTaskContinuation:RunOrScheduleAction(Action, Boolean, Task&)
System.Threading.Tasks.Task:FinishContinuations()
System.Threading.Tasks.Task`1:TrySetResult(TResult)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(TResult)
Unity.Services.Multiplay.Http.<MakeRequestAsync>d__1:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.Tasks.AwaitTaskContinuation:RunOrScheduleAction(Action, Boolean, Task&)
System.Threading.Tasks.Task:FinishContinuations()
System.Threading.Tasks.Task`1:TrySetResult(TResult)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(TResult)
Unity.Services.Multiplay.Http.<CreateWebRequestAsync>d__3:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.ThreadPoolWorkQueue:Dispatch()

[ line 729763672]

Then I was able to solve this by replacing the WaitForCompletion() with awaiting the Task (await taskName.Task), but encounter this error when starting up a session in Photon Fusion:

   Graphics device is null.
UnityEngine.Resources:Load(String)
Fusion.<>c:<Reload>b__6_0()
System.Lazy`1:ViaFactory(LazyThreadSafetyMode)
System.Lazy`1:CreateValue()
Fusion.NetworkProjectConfig:get_Global()
Fusion.NetworkRunner:StartGame(StartGameArgs)
ServerLauncher:StartSimulation(NetworkRunner, Int32, String, String, String, String, Dictionary`2, Int32)
<OnAllocate>d__5:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
System.Threading.ThreadPoolWorkQueue:Dispatch()

The server runs in a batchMode, meaning the Launch Parameters are -nographics -batchmode.

It sounds like a very standard scenario, but I couldn't find any solution anywhere, including approaching the Multiplay support team.

Can someone shed some light on this?

\$\endgroup\$
7
  • \$\begingroup\$ I wonder if one of the addressables is referencing a graphical asset that tries to load a texture/shader/etc using the non-existent graphics device as it loads. Can you make a new project with just a single addressable that triggers this problem, just to narrow down the set of properties that cause it? It might be possible to use the trick shown here to exclude asset references that are needed only for graphics from the server build. \$\endgroup\$
    – DMGregory
    Commented Mar 3, 2023 at 12:49
  • \$\begingroup\$ I believe that's not the issue. I tried instantiating several prefabs, that basically have 3 components - Transform, and 2 other scripts. That are not visuals are handling/referencing visuals in one way or another... The app crashes on the first addressable being instantiated, no matter which one it is... \$\endgroup\$ Commented Mar 3, 2023 at 16:47
  • \$\begingroup\$ I notice you have threading related items in the log. Does this error also happen when you instantiate the addressable from a main thread function like Start()? \$\endgroup\$
    – DMGregory
    Commented Mar 3, 2023 at 17:25
  • \$\begingroup\$ The threading you're mentioning is the InstantiateAsync thread or the function that runs the InstantiateAsync? I tried running it from the Start() as you suggested.. same behavior.. \$\endgroup\$ Commented Mar 4, 2023 at 14:13
  • \$\begingroup\$ The server fails on the GetAssetBundle() which is not neccessatly related to the specific asset, but to all the assets within the bundle. As far as I understand, it requires only one asset to not be compatible to make the server crash. More than that, when I try to catch the exception, the server crashes before it logs the error to the file. Tried logging the Addressables but all the logs it printed weren't related to GetAssetBundle(), but only to the initialization process.. \$\endgroup\$ Commented Mar 5, 2023 at 18:57

1 Answer 1

1
\$\begingroup\$

Apparently, the issue was caused by not instantiating the assets from the main thread.

I made a custom implementation for forcing the method to run in the main thread, and it is now solved.

This is the class that I created to force a method to run in the main thread:

using System.Collections.Generic;
using UnityEngine;

public class UnityMainThreadDispatcher : MonoBehaviour
{
public static UnityMainThreadDispatcher _instance;
private static Queue<System.Action> _actionQueue = new 
   Queue<System.Action>();

private void Awake()
{
    if (!Application.isBatchMode)
    {
        Destroy(this.gameObject);
    }

    if (_instance != null)
    {
        Destroy(gameObject);
    }
    else
    {
        _instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

void Update()
{
    lock (_actionQueue)
    {
        while (_actionQueue.Count > 0)
        {
            _actionQueue.Dequeue().Invoke();
        }
    }
}

public void ExecuteOnMainThread(System.Action action)
{
    lock (_actionQueue)
    {
        _actionQueue.Enqueue(action);
    }
}
}

Then, for all the code that I want to force to the main thread, I use this:

        UnityMainThreadDispatcher._instance.ExecuteOnMainThread(async () =>
    {
       // Enter code here
    });
\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .