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<Frame^>(Window::Current->Content);
// 当窗口已包含内容时,请勿重复初始化应用程序,
// 仅确保窗口处于活动状态
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
// 如果应用程序已导出为 Holographic,请检查设备是否真正支持这种类型,
// 否则我们将应用程序视为普通 XAML 应用程序
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^>(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 线程上运行,所以在关卡完全加载之前,UI 将无响应。这就是为什么 Unity 始终在其他不同的线程上运行游戏的原因。
在此处阅读有关 UI 线程的更多信息 - http://msdn.microsoft.com/en-us/library/windows/apps/hh994635.aspx
您还可以将自定义命令行参数作为字符串数组传递到 AppCallbacks 构造函数中。
注意:位于 App.xaml.cpp 和 MainPage.xaml.c[[ 中的代码始终在 UI 线程上运行(除非从 InvokeOnAppThread 函数进行调用)。
appCallbacks->SetSwapChainPanel(m_DXSwapChainPanel);
此语句简单地将 XAML 控件传递给 Unity,此控件将用作 DirectX 11 的渲染目标。
appCallbacks->SetCoreWindowEvents(Window::Current->CoreWindow);
设置 Unity 的核心窗口,Unity 订阅以下事件(可能会有更多,具体取决于更新此信息的时间):
appCallbacks->InitializeD3DXAML();
这是 Unity 的主要初始化函数,负责执行以下操作:
此时,当 Unity 完成加载第一个关卡的操作时,它将进入主循环。
在应用程序线程上调用委托,当您想从 UI 线程执行脚本函数时非常有用。
在 UI 线程上调用委托,当您想从脚本调用特定于 XAML 的 API 时非常有用。
如果当前在应用程序线程中运行,返回 true。
如果当前在 UI 线程中运行,返回 true。
D3D 应用程序的初始化函数。
D3D 应用程序使用的函数,用于进入主循环。
第一个关卡完全加载时,返回 true。
为应用程序设置命令行参数,必须在 InitializeD3DWindow 和 InitializeD3DXAML 之前调用。
设置应用程序参数,稍后可从 Unity API 访问 - UnityEngine.WSA.Application.arguments。
此函数已过时,不执行任何操作。在以前的 Unity 版本中,需要使用此函数才能为回调(如 UnityRenderEvent)注册原生插件。所有插件现在都自动注册。未来更新中将删除此函数。
解析文件中的命令行参数,参数必须用空格分隔。
如果传递 1,则暂停 Unity,如果传递 0,则取消暂停,希望暂时冻结游戏时(比如创建游戏的快照时)有用。
启用/禁用输入。
如果 Unity 将处理传入的输入,返回 true。
设置用于触发屏幕键盘的控件。在脚本中请求屏幕键盘时,此控件将直接获得焦点。应该用控件进行调用,这样会打开处于焦点状态的键盘。
返回控件,即当前用于触发键盘输入的控件。请参阅 SetKeyboardTriggerControl。
设置系统光标。为 CoreWindow 和独立输入源(如果使用)设置给定光标。
将系统光标设置为自定义设置。参数为光标资源 ID。为 CoreWindow 和独立输入源(如果使用)设置光标。