How to embed unity (exe) in maui windows?

amin rahimzadeh 0 Reputation points
2024-12-09T23:36:19.3766667+00:00

hi

I used this method to embed Unity into MAUI but it doesn't work properly

I want it to be placed inside a view and resize when the page is resized

It works fine in Winforms

using System.Diagnostics;
using System.Formats.Tar;
using System.Runtime.InteropServices;

namespace Momentum
{
    public partial class MainPage : ContentPage
    {
        [DllImport("User32.dll")]
        static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);

        internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
        [DllImport("user32.dll")]
        internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        private Process process;
        private IntPtr unityHWND = IntPtr.Zero;

        private const int WM_ACTIVATE = 0x0006;
        private readonly IntPtr WA_ACTIVE = new IntPtr(1);
        private readonly IntPtr WA_INACTIVE = new IntPtr(0);

        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // Delay handler access
            Task.Delay(2000).ContinueWith(_ =>
            {
                StartUnityProcess();
            });
        }

        private void StartUnityProcess()
        {
            try
            {
                if (File.Exists("C:\\Users\\AMIN\\Desktop\\unity\\unity.exe"))
                {
                    process = new Process
                    {
                        StartInfo =
                    {
                        FileName = "C:\\Users\\AMIN\\Desktop\\unity\\unity.exe", // Path to Unity app
                        Arguments = $"-parentHWND {GetNativePanelHandle()} {Environment.CommandLine}",
                        UseShellExecute = true,
                        CreateNoWindow = true
                    }
                    };

                    process.Start();
                    process.WaitForInputIdle();

                    IntPtr hwnd = GetNativePanelHandle();
                    if (hwnd == IntPtr.Zero)
                    {
                        Debug.WriteLine("Failed to retrieve valid HWND.");
                        return;
                    }
                    Task.Delay(2000).Wait();
                    bool result =  EnumChildWindows(hwnd, WindowEnum, IntPtr.Zero);

                    if (!result)
                    {
                        Debug.WriteLine("EnumChildWindows failed.");
                    }
                    else
                    {
                        Debug.WriteLine("EnumChildWindows succeeded.");
                    }

                }
                else
                {
                    DisplayAlert("Error", "file not exist", "OK");
                }

            }
            catch (Exception ex)
            {
                DisplayAlert("Error", $"{ex.Message}. Check if Container.exe is placed next to Child.exe.", "OK");
            }
        }

        private IntPtr GetNativePanelHandle()
        {
#if WINDOWS
            // Retrieve the window handle for the native panel
            var windowHandle = (IntPtr)(UnityContainer.Window.Handler.PlatformView as MauiWinUIWindow).WindowHandle;
            if (windowHandle == IntPtr.Zero)
            {
                Debug.WriteLine("Failed to retrieve window handle.");
            }

            Debug.WriteLine($"windowHandle type: {windowHandle}");
            return windowHandle;
#else
        throw new PlatformNotSupportedException("Unity embedding only supported on Windows.");
#endif
        }

        private int WindowEnum(IntPtr hwnd, IntPtr lparam)
        {
            unityHWND = hwnd;
            Debug.WriteLine($"Unity window handle: {unityHWND}");
            ActivateUnityWindow();
            return 1;
        }

        private void ActivateUnityWindow()
        {
            SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
        }


        private void DeactivateUnityWindow()
        {
            SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
        }

        private void OnResize(object sender, EventArgs e)
        {
#if WINDOWS
            var rect = UnityContainer.Bounds;
            MoveWindow(unityHWND, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height, true);
            ActivateUnityWindow();
#endif
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            try
            {
                process.CloseMainWindow();
                Thread.Sleep(1000);

                if (!process.HasExited)
                    process.Kill();
            }
            catch (Exception) { }
        }


    }

}

Developer technologies | .NET | .NET MAUI
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 50,126 Reputation points Microsoft External Staff
    2024-12-10T05:26:36.4033333+00:00

    Hello,

    On the Windows platform, Maui uses WinUI3 technology, which is different from WPF technology. Currently WinUI3 does not support displaying Unity programs in controls. There is a feature request submitted in the github.

    Please continue to follow Proposal: Support embedding another executable inside a UserControl with WinUI 3 desktop (win32). #4501 to avoid missing updates from the development team.

    Best Regards,

    Alec Liu.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.