Менеджер сценариев Unity.Функция LoadScene() не работает при вызове из внешнего события

#c# #unity3d #dll

Вопрос:

Я написал библиотеку классов за пределами Unity (и поместил ее в Unity в виде библиотеки DLL), в которой я объявил публичное событие, которое я слушаю из своего кода unity. Событие вызывается из библиотеки DLL. Когда событие было вызвано, методы, которые подписываются на событие, выполняются, как я и ожидал, за исключением UnityEngine.Сценография.Диспетчер сцен.LoadScene() не выполняется, а также приводит к тому, что любой код после него не запускается.

 using UnityEngine.SceneManagement; using MyDLL; // this namespace has the Client.OnConnected event public class GameManager : MonoBehaviour {  void Awake()   {  Client.OnConnected  = () =gt; {  Debug.Log("Connected to Server");  SceneManager.LoadScene("Main");  Debug.Log("Main Scene Loaded");  };  } }  

Когда Клиент.Вызывается событие OnConnected, я вижу, что «Подключено к серверу» регистрируется, но сцена «Основная» не загружается, а «Основная сцена загружена» не регистрируется.

У кого-нибудь есть какие-либо идеи, почему это происходит и как это обойти?

Ответ №1:

Ваша проблема, скорее всего, заключается в том, что большая часть API Unity может быть вызвана только из основного потока Unity.

Ваше OnConnected событие, похоже, вызывается асинхронно.

Вам нужно будет отправить этот вызов обратно в основной поток Unity.

Часто используемый шаблон для этого заключается в следующем:

 public class GameManager : MonoBehaviour {  // A thread safe Queue we can append actions to that shall be executed in the next Update call  private readonly ConcurrentQueuelt;Actiongt; _actions = new ConcurrentQueuelt;Actiongt;();   void Awake()   {  Client.OnConnected  = OnClientConnected;  }   private void OnClientConnected()   {  // Instead of immediately exciting the callback append it to the   // actions to be executed in the next Update call on the Unity main thread  _actions.Enqueue(() =gt;   {  Debug.Log("Connected to Server");  SceneManager.LoadScene("Main");  Debug.Log("Main Scene Loaded");  };  }   // In the main thread work of the dispatched actions  private void Update ()  {  while(_actions.Count gt; 0)  {  if(_actions.TryDequeue(out var action))  {  action?.Invoke();  }  }  } }