Вы можете назвать класс AppCallbacks связующим звеном между вашим основным приложением и механизмом Unity. Здесь мы попытаемся объяснить, что именно делает каждый вызов AppCallbacks. Давайте создадим решение и изучим файлы App.xaml.cpp и MainPage.xaml.cpp.
App::App()
{
InitializeComponent();
SetupOrientation();
m_AppCallbacks = ref new AppCallbacks();
}
void App::OnLaunched(LaunchActivatedEventArgs^ e)
{
m_SplashScreen = e->SplashScreen;
InitializeUnity(e->Arguments);
}
void App::InitializeUnity(String^ args)
{
ApplicationView::GetForCurrentView()->SuppressSystemOverlays = true;
m_AppCallbacks->SetAppArguments(args);
auto rootFrame = safe_cast(Window::Current->Content);
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == nullptr && !m_AppCallbacks->IsInitialized())
{
rootFrame = ref new Frame();
Window::Current->Content = rootFrame;
#if !UNITY_HOLOGRAPHIC
Window::Current->Activate();
#endif
rootFrame->Navigate(TypeName(MainPage::typeid ));
}
Window::Current->Activate();
}
MainPage::MainPage()
{
m_SplashScreenRemovalEventToken.Value = 0;
m_OnResizeRegistrationToken.Value = 0;
InitializeComponent();
NavigationCacheMode = ::NavigationCacheMode::Required;
auto appCallbacks = AppCallbacks::Instance;
bool isWindowsHolographic = false;
#if UNITY_HOLOGRAPHIC
// If application was exported as Holographic check if the device actually supports it,
// otherwise we treat this as a normal XAML application
isWindowsHolographic = AppCallbacks::IsMixedRealitySupported();
#endif
if (isWindowsHolographic)
{
appCallbacks->InitializeViewManager(Window::Current->CoreWindow);
}
else
{
m_SplashScreenRemovalEventToken = appCallbacks->RenderingStarted += ref new RenderingStartedHandler(this, &MainPage::RemoveSplashScreen);
appCallbacks->SetSwapChainPanel(m_DXSwapChainPanel);
appCallbacks->SetCoreWindowEvents(Window::Current->CoreWindow);
appCallbacks->InitializeD3DXAML();
m_SplashScreen = safe_cast(App::Current)->GetSplashScreen();
auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;
ThreadPool::RunAsync(ref new WorkItemHandler([this, dispatcher](IAsyncAction^)
{
GetSplashBackgroundColor(dispatcher);
}));
OnResize();
m_OnResizeRegistrationToken = Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler([this](Object^, WindowSizeChangedEventArgs^)
{
OnResize();
});
}
}
m_AppCallbacks = ref new AppCallbacks();
Давайте подробнее рассмотрим класс AppCallbacks. Когда вы его создаете, Unity создает новый поток под названием «AppThread». Это сделано потому, что есть ограничение от Microsoft — если ваше приложение не отвечает через 5 секунд, вы не сможете пройти WACK (сертификацию приложений Windows). (Подробнее можно прочитать здесь — http ://msdn.microsoft.com/en-us/library/windowsphone/develop/hh184840(v=vs.105).aspx) Представьте, что ваш первый уровень довольно большой и требует много времени для нагрузка. Поскольку ваше приложение работает в UI(пользовательский интерфейс) Позволяет пользователю взаимодействовать с вашим приложением. В настоящее время Unity поддерживает три системы пользовательского интерфейса. Подробнее
Посмотрите в ветке Словарь, пользовательский интерфейс не будет отвечать до тех пор, пока ваш уровень не будет полностью загружен. . Вот почему Unity всегда запускает вашу игру в другом потоке.
Подробнее об интерфейсе читайте здесь: http:// msdn.microsoft.com/en-us/library/windows/apps/hh994635.aspx
Вы также можете передать пользовательские аргументы командной строки в виде строкового массива в конструктор AppCallbacks.
Примечание. Код, расположенный в App.xaml.cpp, MainPage.xaml.c[[, всегда выполняется в потоке пользовательского интерфейса, если только он не вызывается из функции InvokeOnAppThread.
appCallbacks->SetSwapChainPanel(m_DXSwapChainPanel);
Это просто передает элемент управления XAML в Unity, который будет использоваться в качестве цели рендеринга для DirectX 11.
appCallbacks->SetCoreWindowEvents(Window::Current->CoreWindow);
Устанавливает основное окно для Unity, Unity подписывается на следующие события (их может быть больше, в зависимости от того, когда эта информация была обновлена):
- VisibilityChanged
- Closed
- PointerCursor
- SizeChanged
- Activated
- CharacterReceived
- PointerPressed
- PointerReleased
- PointerMoved
- PointerCaptureLost
- PointerWheelChanged
- AcceleratorKeyActivated
appCallbacks->ИнициализироватьD3DXAML();
Это основная функция инициализации для Unity, она выполняет следующие действия:
- Инициализирует устройство DirectX 11.
- Загружает первый уровень
В этот момент, когда Unity завершает загрузку первого уровня, он входит в основной цикл.
Другие функции
- void InvokeOnAppThread(элемент AppCallbackItem, bool waitUntilDone)
Вызывает делегата в потоке приложения, что полезно, когда вы хотите выполнить функцию скрипта из потока пользовательского интерфейса.
- void InvokeOnUIThread(элемент AppCallbackItem, bool waitUntilDone)
Вызывает делегата в потоке пользовательского интерфейса. Это полезно, когда вы хотите вызвать какой-либо специфичный для XAML API из ваших скриптовфрагмент кода Это позволяет вам создавать свои собственные Компоненты, запускать игровые события, изменять свойства Компонентов с течением времени и реагировать на ввод данных пользователем любым удобным для вас способом. Подробнее
См. в Словарь.
- bool RunningOnAppThread()
Возвращает true, если вы в данный момент работаете в потоке приложения.
- bool RunningOnUIThread()
Возвращает true, если вы в данный момент работаете в потоке пользовательского интерфейса.
- void InitializeD3DWindow()
Функция инициализации для приложения D3D.
- пустой запуск()
Функция, используемая приложением D3D для входа в основной цикл.
- bool IsInitialized()
Возвращает true, когда первый уровень полностью загружен.
- void AddCommandLineArg(string arg)
Задает аргумент командной строки для приложения, должен вызываться перед InitializeD3DWindow, InitializeD3DXAML.
- void SetAppArguments(string arg) / string GetAppArguments()
Устанавливает аргументы приложения, к которым позже можно получить доступ из API Unity — UnityEngine.WSA.Application.arguments.
- void LoadGfxNativePlugin(string pluginFileName)
Эта функция устарела и ничего не делает. В предыдущих версиях Unity это было необходимо для регистрации собственных подключаемых модулей для обратных вызовов, таких как UnityRenderEvent. Все плагины теперь регистрируются автоматически. Эта функция будет удалена в будущем обновлении.
- void ParseCommandLineArgsFromFiles(string fileName)
Разбирает аргументы командной строки из файла, аргументы должны быть разделены пробелами.
- bool UnityPause(int pause)
Приостанавливает Unity, если вы проходите 1, возобновляет паузу, если вы проходите 0, полезно, если вы хотите временно заморозить свою игру, например, когда ваша игра щелкнула.
- void UnitySetInput (bool включен)
Включает/отключает ввод.
- bool UnityGetInput()
Возвращает true, если Unity будет обрабатывать входящий ввод.
- void SetKeyboardTriggerControl(Windows.UI.Xaml.Controls.Control ctrl)
Устанавливает элемент управления, который будет использоваться для запуска на экранной клавиатуре. Этот элемент управления просто получит фокус, когда в скриптах запрашивается экранная клавиатура. Должен вызываться с контролем, который открывает клавиатуру в фокусе.
- Windows.UI.Xaml.Controls.Control GetKeyboardTriggerControl()
Возвращает элемент управления, используемый в данный момент для запуска ввода с клавиатуры. См. раздел SetKeyboardTriggerControl.
- void SetCursor(курсор Windows.UI.Core.CoreCursor)
Устанавливает системный курсор. Данный curosr устанавливается как для CoreWindow, так и для независимого источника ввода (если он используется).
- void SetCustomCursor(целочисленный идентификатор без знака)
Устанавливает системный курсор на пользовательский. Параметр - идентификатор ресурса курсора. Курсор устанавливается как для CoreWindow, так и для независимого источника ввода (если он используется).