Version: 2019.4
通用 Windows 平台:关联启动
通用 Windows 平台:C# 脚本中的 WinRT API

AppCallbacks 类

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 订阅以下事件(可能会有更多,具体取决于更新此信息的时间):

  • VisibilityChanged
  • Closed
  • PointerCursor
  • SizeChanged
  • Activated
  • CharacterReceived
  • PointerPressed
  • PointerReleased
  • PointerMoved
  • PointerCaptureLost
  • PointerWheelChanged
  • AcceleratorKeyActivated

appCallbacks->InitializeD3DXAML();

这是 Unity 的主要初始化函数,负责执行以下操作:

  • 初始化 DirectX 11 设备
  • 加载第一个关卡

此时,当 Unity 完成加载第一个关卡的操作时,它将进入主循环。

其他函数

  • void InvokeOnAppThread(AppCallbackItem item, bool waitUntilDone)

在应用程序线程上调用委托,当您想从 UI 线程执行脚本函数时非常有用。

  • void InvokeOnUIThread(AppCallbackItem item, bool waitUntilDone)

在 UI 线程上调用委托,当您想从脚本调用特定于 XAML 的 API 时非常有用。

  • bool RunningOnAppThread()

如果当前在应用程序线程中运行,返回 true。

  • bool RunningOnUIThread()

如果当前在 UI 线程中运行,返回 true。

  • void InitializeD3DWindow()

D3D 应用程序的初始化函数。

  • void Run()

D3D 应用程序使用的函数,用于进入主循环。

  • bool IsInitialized()

第一个关卡完全加载时,返回 true。

  • void AddCommandLineArg(string arg)

为应用程序设置命令行参数,必须在 InitializeD3DWindow 和 InitializeD3DXAML 之前调用。

  • void SetAppArguments(string arg) / string GetAppArguments()

设置应用程序参数,稍后可从 Unity API 访问 - UnityEngine.WSA.Application.arguments

  • void LoadGfxNativePlugin(string pluginFileName)

此函数已过时,不执行任何操作。在以前的 Unity 版本中,需要使用此函数才能为回调(如 UnityRenderEvent)注册原生插件。所有插件现在都自动注册。未来更新中将删除此函数。

  • void ParseCommandLineArgsFromFiles(string fileName)

解析文件中的命令行参数,参数必须用空格分隔。

  • bool UnityPause(int pause)

如果传递 1,则暂停 Unity,如果传递 0,则取消暂停,希望暂时冻结游戏时(比如创建游戏的快照时)有用。

  • void UnitySetInput(bool enabled)

启用/禁用输入。

  • bool UnityGetInput()

如果 Unity 将处理传入的输入,返回 true。

  • void SetKeyboardTriggerControl(Windows.UI.Xaml.Controls.Control ctrl)

设置用于触发屏幕键盘的控件。在脚本中请求屏幕键盘时,此控件将直接获得焦点。应该用控件进行调用,这样会打开处于焦点状态的键盘。

  • Windows.UI.Xaml.Controls.Control GetKeyboardTriggerControl()

返回控件,即当前用于触发键盘输入的控件。请参阅 SetKeyboardTriggerControl。

  • void SetCursor(Windows.UI.Core.CoreCursor cursor)

设置系统光标。为 CoreWindow 和独立输入源(如果使用)设置给定光标。

  • void SetCustomCursor(unsigned int id)

将系统光标设置为自定义设置。参数为光标资源 ID。为 CoreWindow 和独立输入源(如果使用)设置光标。

通用 Windows 平台:关联启动
通用 Windows 平台:C# 脚本中的 WinRT API