2017-05-18 105 views
6

Chcę stworzyć nowe oprogramowanie CAD w WPF i zamiast używać WPF 3D, można użyć Unity3D jako mojego silnika graficznego, który potrafi obracać, przesuwać, powiększać i wyświetlać obiekty graficzne 3D na podstawie moich obiektów danych w WPF?Osadzanie aplikacji Unity3D wewnątrz aplikacji WPF

Powodem, dla którego zadaję to pytanie, Unity jest silnikiem gry, używa C# jako skryptu, ale nie zapewnia żadnej integracji z aplikacją WPF (osadza Unity w WPF).

Zadałem pytanie na forum jedności, nie mogłem znaleźć żadnej dobrej odpowiedzi, więc proszę o więcej.

+0

Tak, można to zrobić z Unity. Poważnie jednak, możesz przesuwać, obracać i powiększać za pomocą dowolnego silnika gry 3D, więc nie mogę powiedzieć, o co chodzi w tym pytaniu. – Programmer

+0

Dziękuję bardzo. Zmodyfikowałem moje pytanie, proszę spojrzeć. Czy kiedykolwiek próbowałeś używać WPF jako głównej aplikacji i wywoływałeś Unity3D, aby pokazać wyświetlacz graficzny? – ParkAtStreet

+0

Używany WPF przed, ale nie z Unity. WPF jest tylko dla Windows. Jeśli chcesz go użyć, użyj go. Jeśli chcesz użyć Unity, idź do Unity. Nie widzę potrzeby mieszania tych dwóch. Będziesz musiał skończyć ze skomplikowaną aplikacją, która działa tylko w systemie Windows. – Programmer

Odpowiedz

8

Można to zrobić, ale warto zauważyć, że będzie działać tylko w systemie Windows.

Ciężko było to zrobić, ale ostatnio Unity (4.5.5p1) dodała polecenie -parentHWND, które można wykorzystać do osadzenia programu w innym programie. Wszystko, co musisz zrobić, to zbudować swoją aplikację Unity, a następnie z WPF, uruchom ją z interfejsem API Process. Następnie możesz przekazać parametr -parentHWND do aplikacji Unity.

process.StartInfo.FileName = "YourUnityApp.exe"; 
process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.ToInt32() + " " + Environment.CommandLine; 

Do komutacji między tymi dwoma użytkownikami można użyć protokołu TCP lub Named Pipes.

Poniżej znajduje się pełna próbka kodu do umieszczenia na stronie internetowej Unity. Możesz uzyskać cały projekt here. Upewnij się, że nazwa pliku exe kompilacji Unity "UnityGame.exe" następnie umieść go w tym samym katalogu, co program exe WPF.

namespace Container 
{ 
    public partial class Form1 : Form 
    { 
     [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 Form1() 
     { 
      InitializeComponent(); 

      try 
      { 
       process = new Process(); 
       process.StartInfo.FileName = "UnityGame.exe"; 
       process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.ToInt32() + " " + Environment.CommandLine; 
       process.StartInfo.UseShellExecute = true; 
       process.StartInfo.CreateNoWindow = true; 

       process.Start(); 

       process.WaitForInputIdle(); 
       // Doesn't work for some reason ?! 
       //unityHWND = process.MainWindowHandle; 
       EnumChildWindows(panel1.Handle, WindowEnum, IntPtr.Zero); 

       unityHWNDLabel.Text = "Unity HWND: 0x" + unityHWND.ToString("X8"); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message + ".\nCheck if Container.exe is placed next to UnityGame.exe."); 
      } 

     } 

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

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

     private int WindowEnum(IntPtr hwnd, IntPtr lparam) 
     { 
      unityHWND = hwnd; 
      ActivateUnityWindow(); 
      return 0; 
     } 

     private void panel1_Resize(object sender, EventArgs e) 
     { 
      MoveWindow(unityHWND, 0, 0, panel1.Width, panel1.Height, true); 
      ActivateUnityWindow(); 
     } 

     // Close Unity application 
     private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
     { 
      try 
      { 
       process.CloseMainWindow(); 

       Thread.Sleep(1000); 
       while (!process.HasExited) 
        process.Kill(); 
      } 
      catch (Exception) 
      { 

      } 
     } 

     private void Form1_Activated(object sender, EventArgs e) 
     { 
      ActivateUnityWindow(); 
     } 

     private void Form1_Deactivate(object sender, EventArgs e) 
     { 
      DeactivateUnityWindow(); 
     } 
    } 
} 
+1

Dziękuję bardzo ... – ParkAtStreet