Перейти к основному содержимому
Версия: 3.3.2

Вызов Методов Обратного Вызова В Главном Потоке Unity

Функции обратного вызова плагина Appodeal запускаются в главном потоке iOS или Android, но не в главном потоке Unity. Так как любые изменения UI (изменение цвета, позиции объектов, размеров, текстов и т.д.) разрешены только в главном потоке, нельзя выполнять их из функций обратного вызова напрямую.

Важно понимать, что невозможно получить уведомления о каких-либо событиях в главном потоке Unity в тот момент, когда отображается любая полноэкранная реклама. Все потому, что Unity останавливает основной поток в тот момент, когда сцену что-либо перекрывает. Поэтому ваш скрипт получит уведомления о некоторых событиях (например OnInterstitialShown или OnRewardedVideoFinished) в главном потоке только после закрытия рекламы. Но те же самые функции обратного вызова будут работать без каких-либо задержек в главных потоках Android и iOS.

Как же правильно обработать события Appodeal плагина, чтобы избежать проблем с изменением UI из неправильного потока? Наиболее простой путь - использовать логические флаги и метод Update класса MonoBehaviour:

public class SomeClass : MonoBehaviour
{
bool videoFinished = false;
double rewardAmount;
string rewardName;

public void OnRewardedVideoFinished(object sender, RewardedVideoFinishedEventArgs e)
{
rewardAmount = e.Amount;
rewardName = e.Currency;

// It's important to set flag to true only after all required parameters
videoFinished = true;
}

// Update method always performs in the main Unity thread
void Update()
{
if(videoFinished)
{
// Don't forget to set flag to false
videoFinished = false;
// Do something with rewardAmount and rewardName
}
}
}

Другой, возможно более комфортный способ - UnityMainThreadDispatcher. Для того, чтобы воспользоваться им:

  1. Скачайте скрипт и префаб.
  2. Импортируйте скачанные файлы в проект.
  3. Добавьте UnityMainThreadDispatcher.prefab на вашу сцену (или все сцены, на которых вы собираетесь делать какие-либо изменения UI после событий плагина).
  4. Используйте метод UnityMainThreadDispatcher.Instance().Enqueue(), чтобы выполнить необходимые изменения:
public void OnRewardedVideoFinished(object sender, RewardedVideoFinishedEventArgs e)
{
UnityMainThreadDispatcher.Instance().Enqueue(()=> {
Debug.Log($"Appodeal. Video Finished: {e.Amount} {e.Currency}")
});
}

И, наконец, официальный способ передать сообщение в главный поток Unity - метод UnitySendMessage. Этот метод платформозависимый, поэтому для его применения необходимо сделать изменения в нативном Android и iOS коде.

Больше информации об этом методе вы можете найти в официальной документации Android и iOS.