Version: 2020.1
言語: 日本語
Universal Windows Platform: Association launching
Universal Windows Platform: WinRT API in C# scripts

AppCallbacks class

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

This simply passes a XAML control to Unity which will be used as a render target for DirectX 11.

appCallbacks->SetCoreWindowEvents(Window::Current->CoreWindow);

Sets the core window for Unity, Unity subscribes to the following events (there may be more, depending on when this information was updated) :

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

appCallbacks->InitializeD3DXAML();

This is main initialization function for Unity, it does following things:

  • Initializes DirectX 11 device
  • Loads first level

At this point, when Unity finishes loading first level, it enters main loop.

Other functions

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

Invokes a delegate on UI thread, useful when you want to invoke something XAML specific API from your scripts.

  • bool RunningOnAppThread()

Returns true, if you’re currently running in application thread.

  • bool RunningOnUIThread()

Returns true, if you’re currently running in UI thread.

  • void InitializeD3DWindow()

Initialization function for D3D application.

  • void Run()

Function used by D3D application, for entering main loop.

  • bool IsInitialized()

Returns true, when first level is fully loaded.

  • void AddCommandLineArg(string arg)

Sets a command line argument for application, must be called before InitializeD3DWindow, InitializeD3DXAML.

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

Sets application arguments, which can be later accessed from Unity API - UnityEngine.WSA.Application.arguments.

  • void LoadGfxNativePlugin(string pluginFileName)

This function is obsolete and does nothing. In previous versions of Unity, this was needed to register native plugins for callbacks such as UnityRenderEvent. All plugins are now registered automatically. This function will be removed in a future update.

  • void ParseCommandLineArgsFromFiles(string fileName)

Parses command line arguments from a file, arguments must be separated by white spaces.

  • bool UnityPause(int pause)

Pauses Unity if you pass 1, unpauses if you pass 0, useful if you want to temporary freeze your game, for ex., when your game is snapped.

  • void UnitySetInput(bool enabled)

Enables/Disables input.

  • bool UnityGetInput()

Returns true, if Unity will process incoming input.

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

Sets the control to be used for triggering on screen keyboard. This control will simply receive focus, when on screen keyboard is requested in scripts. Should be called with control, that does open keyboard on focus.

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

Returns control, currently used control for triggering keyboard input. See SetKeyboardTriggerControl.

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

Sets system cursor. The given curosr is set for both CoreWindow and independent input source (if used).

  • void SetCustomCursor(unsigned int id)

Sets system cursor to custom. Parameter is cursor resource ID. Cursor is set for both CoreWindow and independent input source (if used).

Universal Windows Platform: Association launching
Universal Windows Platform: WinRT API in C# scripts