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

AppCallbacks 类

You could call the AppCallbacks class a bridge between your main application and the Unity engine. Here, we’ll try to explain what every call to AppCallbacks exactly does. Let’s build solution and explore App.xaml.cpp and MainPage.xaml.cpp files.

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);

    // 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^>(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();

Let’s take a closer look at AppCallbacks class. When you create it, Unity creates a new thread called “AppThread”. This is done because there’s a restriction from Microsoft - if your application does not become responsive after 5 seconds you’ll fail to pass WACK (Windows Application Certification). (You can read more here - http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh184840(v=vs.105).aspx) Imagine if your first level is pretty big and takes a significant amount of time to load. Because your application is running on UI thread, the UI will be unresponsive until your level is fully loaded. That’s why Unity always runs your game on different thread.

Read more on the UI thread here - http://msdn.microsoft.com/en-us/library/windows/apps/hh994635.aspx

You can also pass custom command line arguments as string array into the AppCallbacks constructor.

Note: Code located in App.xaml.cpp, MainPage.xaml.c[[ is always running on UI thread, unless called from InvokeOnAppThread function.

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 的主要初始化函数,负责执行以下操作:

  • Initializes DirectX 11 device
  • Loads first level

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

其他函数

  • void InvokeOnAppThread(AppCallbackItem item, bool waitUntilDone)

Invokes a delegate on application thread, which is useful when you want to execute your script function from UI thread.

  • 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