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) { }
}
}
}