Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Embeding Unity3D within Qt application

Embeding Unity3D within Qt application

Scheduled Pinned Locked Moved Unsolved Qt for Python
5 Posts 4 Posters 894 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Pythonic person
    wrote on 13 Mar 2024, 17:56 last edited by
    #1

    Hi, Well i am planning to develop a desktop application using Qt, and i would like to embed my game which built via Unity3D.

    Unity3D provide a seamless way to embed it's window into any external application by passing --parentHWND as an argument.

    here is my example of doing so:

    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    
    
    class Unity:
    
        def __init__(self, unity_container):
            container_widget = unity_container
            self.container_widget_hwnd = int(container_widget.winId())
    
        def setup_unity(self) -> None:
            self.unity = QProcess()
            self.unity.setProgram("path/MyUnityGame.exe")
            self.unity.setArguments(["-parentHWND", str(self.container_widget_hwnd)])
            self.unity.start()
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("PyQt Unity Integration Example with Stacked Widgets")
            self.setGeometry(100, 100, 800, 600)
    
            # Create the main layout using QGridLayout
            self.main_layout = QGridLayout()
            self.setCentralWidget(QWidget())  # Set a central widget to use the layout
            self.centralWidget().setLayout(self.main_layout)
    
            # Create the stacked widget and add it to the main layout
            self.stacked_widget = QStackedWidget()
            self.main_layout.addWidget(self.stacked_widget, 0, 0, 1, 1)  # Add to grid layout
    
            # First widget setup
            self.first_widget = QWidget()
            self.first_layout = QVBoxLayout()
    
            # Setup QGraphicsView and QGraphicsScene
            self.scene = QLabel("Hello World!!")
            self.first_layout.addWidget(self.scene)  # Add the view to the layout
    
            # Button to switch to Unity
            self.switch_to_unity_button = QPushButton("Switch to Unity")
            self.switch_to_unity_button.clicked.connect(self.switch_to_unity)
            self.first_layout.addWidget(self.switch_to_unity_button)
    
            self.first_widget.setLayout(self.first_layout)
    
            # Second widget (container for Unity)
            self.second_widget = QWidget()
            self.second_layout = QVBoxLayout()
            self.switch_back_button = QPushButton("Switch Back")
            self.switch_back_button.clicked.connect(self.switch_back)
            self.switch_back_button.setVisible(False)  # Initially hidden
            self.second_layout.addWidget(self.switch_back_button)
            self.second_widget.setLayout(self.second_layout)
    
            # Add both widgets to the stacked widget
            self.stacked_widget.addWidget(self.first_widget)
            self.stacked_widget.addWidget(self.second_widget)
    
            # Initialize UnityHandler with the second widget
            self.unity_handler = Unity(self.second_widget)
    
            # Add the switch back button to the grid layout, ensuring it's always on top
            self.main_layout.addWidget(self.switch_back_button, 0, 0, 1, 1, Qt.AlignTop)
            self.second_widget.show()
            self.unity_handler.setup_unity()
    
        def switch_to_unity(self):
            self.stacked_widget.setCurrentIndex(1)
    
        def switch_back(self):
            self.stacked_widget.setCurrentIndex(0)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec_())
    

    But recently, i found out that Qt doesn't officially support embedding external window, and 99% will leads to unexpected problems which can not be resolve.
    So i got confused!!.
    Any advice whether should i contiune using this approach for my desktop application or should i stop using it?

    here is the references:

    1. Embed Unity within Any external application
    2. Bugs with 'QWidget.winId()'
    J J 2 Replies Last reply 14 Mar 2024, 06:49
    0
    • S SGaist moved this topic from General and Desktop on 13 Mar 2024, 19:47
    • P Pythonic person
      13 Mar 2024, 17:56

      Hi, Well i am planning to develop a desktop application using Qt, and i would like to embed my game which built via Unity3D.

      Unity3D provide a seamless way to embed it's window into any external application by passing --parentHWND as an argument.

      here is my example of doing so:

      import sys
      from PyQt5.QtWidgets import *
      from PyQt5.QtCore import *
      
      
      class Unity:
      
          def __init__(self, unity_container):
              container_widget = unity_container
              self.container_widget_hwnd = int(container_widget.winId())
      
          def setup_unity(self) -> None:
              self.unity = QProcess()
              self.unity.setProgram("path/MyUnityGame.exe")
              self.unity.setArguments(["-parentHWND", str(self.container_widget_hwnd)])
              self.unity.start()
      
      
      class MainWindow(QMainWindow):
          def __init__(self):
              super().__init__()
              self.setWindowTitle("PyQt Unity Integration Example with Stacked Widgets")
              self.setGeometry(100, 100, 800, 600)
      
              # Create the main layout using QGridLayout
              self.main_layout = QGridLayout()
              self.setCentralWidget(QWidget())  # Set a central widget to use the layout
              self.centralWidget().setLayout(self.main_layout)
      
              # Create the stacked widget and add it to the main layout
              self.stacked_widget = QStackedWidget()
              self.main_layout.addWidget(self.stacked_widget, 0, 0, 1, 1)  # Add to grid layout
      
              # First widget setup
              self.first_widget = QWidget()
              self.first_layout = QVBoxLayout()
      
              # Setup QGraphicsView and QGraphicsScene
              self.scene = QLabel("Hello World!!")
              self.first_layout.addWidget(self.scene)  # Add the view to the layout
      
              # Button to switch to Unity
              self.switch_to_unity_button = QPushButton("Switch to Unity")
              self.switch_to_unity_button.clicked.connect(self.switch_to_unity)
              self.first_layout.addWidget(self.switch_to_unity_button)
      
              self.first_widget.setLayout(self.first_layout)
      
              # Second widget (container for Unity)
              self.second_widget = QWidget()
              self.second_layout = QVBoxLayout()
              self.switch_back_button = QPushButton("Switch Back")
              self.switch_back_button.clicked.connect(self.switch_back)
              self.switch_back_button.setVisible(False)  # Initially hidden
              self.second_layout.addWidget(self.switch_back_button)
              self.second_widget.setLayout(self.second_layout)
      
              # Add both widgets to the stacked widget
              self.stacked_widget.addWidget(self.first_widget)
              self.stacked_widget.addWidget(self.second_widget)
      
              # Initialize UnityHandler with the second widget
              self.unity_handler = Unity(self.second_widget)
      
              # Add the switch back button to the grid layout, ensuring it's always on top
              self.main_layout.addWidget(self.switch_back_button, 0, 0, 1, 1, Qt.AlignTop)
              self.second_widget.show()
              self.unity_handler.setup_unity()
      
          def switch_to_unity(self):
              self.stacked_widget.setCurrentIndex(1)
      
          def switch_back(self):
              self.stacked_widget.setCurrentIndex(0)
      
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
          window = MainWindow()
          window.show()
          sys.exit(app.exec_())
      

      But recently, i found out that Qt doesn't officially support embedding external window, and 99% will leads to unexpected problems which can not be resolve.
      So i got confused!!.
      Any advice whether should i contiune using this approach for my desktop application or should i stop using it?

      here is the references:

      1. Embed Unity within Any external application
      2. Bugs with 'QWidget.winId()'
      J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 14 Mar 2024, 06:49 last edited by
      #2

      @Pythonic-person said in Embeding Unity3D within Qt application:

      But recently, i found out that Qt doesn't officially support embedding external window

      Are you sure? It should work, see for example https://forum.qt.io/topic/44091/embed-an-application-inside-a-qt-window-solved

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      P 1 Reply Last reply 14 Mar 2024, 10:53
      0
      • P Pythonic person
        13 Mar 2024, 17:56

        Hi, Well i am planning to develop a desktop application using Qt, and i would like to embed my game which built via Unity3D.

        Unity3D provide a seamless way to embed it's window into any external application by passing --parentHWND as an argument.

        here is my example of doing so:

        import sys
        from PyQt5.QtWidgets import *
        from PyQt5.QtCore import *
        
        
        class Unity:
        
            def __init__(self, unity_container):
                container_widget = unity_container
                self.container_widget_hwnd = int(container_widget.winId())
        
            def setup_unity(self) -> None:
                self.unity = QProcess()
                self.unity.setProgram("path/MyUnityGame.exe")
                self.unity.setArguments(["-parentHWND", str(self.container_widget_hwnd)])
                self.unity.start()
        
        
        class MainWindow(QMainWindow):
            def __init__(self):
                super().__init__()
                self.setWindowTitle("PyQt Unity Integration Example with Stacked Widgets")
                self.setGeometry(100, 100, 800, 600)
        
                # Create the main layout using QGridLayout
                self.main_layout = QGridLayout()
                self.setCentralWidget(QWidget())  # Set a central widget to use the layout
                self.centralWidget().setLayout(self.main_layout)
        
                # Create the stacked widget and add it to the main layout
                self.stacked_widget = QStackedWidget()
                self.main_layout.addWidget(self.stacked_widget, 0, 0, 1, 1)  # Add to grid layout
        
                # First widget setup
                self.first_widget = QWidget()
                self.first_layout = QVBoxLayout()
        
                # Setup QGraphicsView and QGraphicsScene
                self.scene = QLabel("Hello World!!")
                self.first_layout.addWidget(self.scene)  # Add the view to the layout
        
                # Button to switch to Unity
                self.switch_to_unity_button = QPushButton("Switch to Unity")
                self.switch_to_unity_button.clicked.connect(self.switch_to_unity)
                self.first_layout.addWidget(self.switch_to_unity_button)
        
                self.first_widget.setLayout(self.first_layout)
        
                # Second widget (container for Unity)
                self.second_widget = QWidget()
                self.second_layout = QVBoxLayout()
                self.switch_back_button = QPushButton("Switch Back")
                self.switch_back_button.clicked.connect(self.switch_back)
                self.switch_back_button.setVisible(False)  # Initially hidden
                self.second_layout.addWidget(self.switch_back_button)
                self.second_widget.setLayout(self.second_layout)
        
                # Add both widgets to the stacked widget
                self.stacked_widget.addWidget(self.first_widget)
                self.stacked_widget.addWidget(self.second_widget)
        
                # Initialize UnityHandler with the second widget
                self.unity_handler = Unity(self.second_widget)
        
                # Add the switch back button to the grid layout, ensuring it's always on top
                self.main_layout.addWidget(self.switch_back_button, 0, 0, 1, 1, Qt.AlignTop)
                self.second_widget.show()
                self.unity_handler.setup_unity()
        
            def switch_to_unity(self):
                self.stacked_widget.setCurrentIndex(1)
        
            def switch_back(self):
                self.stacked_widget.setCurrentIndex(0)
        
        
        if __name__ == "__main__":
            app = QApplication(sys.argv)
            window = MainWindow()
            window.show()
            sys.exit(app.exec_())
        

        But recently, i found out that Qt doesn't officially support embedding external window, and 99% will leads to unexpected problems which can not be resolve.
        So i got confused!!.
        Any advice whether should i contiune using this approach for my desktop application or should i stop using it?

        here is the references:

        1. Embed Unity within Any external application
        2. Bugs with 'QWidget.winId()'
        J Offline
        J Offline
        JonB
        wrote on 14 Mar 2024, 08:51 last edited by
        #3

        @Pythonic-person
        I had a look through both your references. The former one looks useful for Qt-Unity tips (especially https://forum.unity.com/threads/unity-player-embedded-into-qt-application.537879/#post-5555494), the latter is from 2015 so the issues may still be there or may have changed.

        I think you will have to try your Unity case and see how it goes. It's not clear whether it will be fine or whether there will be some breaking issue which makes it unsatisfactory for your use case.

        1 Reply Last reply
        0
        • J jsulm
          14 Mar 2024, 06:49

          @Pythonic-person said in Embeding Unity3D within Qt application:

          But recently, i found out that Qt doesn't officially support embedding external window

          Are you sure? It should work, see for example https://forum.qt.io/topic/44091/embed-an-application-inside-a-qt-window-solved

          P Offline
          P Offline
          Pythonic person
          wrote on 14 Mar 2024, 10:53 last edited by
          #4

          @jsulm said in Embeding Unity3D within Qt application:

          Are you sure? It should work

          Here what other says:

          "While technically allowed, embedding "alien" windows from external processes that do not use Qt is not officially supported and suffers many issues (you did read the warnings in the documentation, didn't you?). Especially for modern systems and UI toolkits, 99% of the times you'll face some problems that cannot be worked around (partially or completely),"
          Read the comments.

          @JonB, Nice, i will try go wit my approche and will see what will happen.
          i have concerns of what other said in the stack-overflow link i shared early in my first post. they didn't recommend embededing external window in Qt application at all, at least that what i understood.
          Am not sure if that post address and similar to my approach in coding since i don't use createWindowContainer() method, or not?

          @JonB and @jsulm Thank you both for your time.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SamiV123
            wrote on 14 Mar 2024, 18:37 last edited by
            #5

            Usually this type of thing is done via interop.

            Your Unity (or whatever graphics system) would render to a texture.

            You use your platform (Windows, DXGI) resource sharing to acquire resource specific handles and mutexes.

            Then several processes can access the same data. Once your game engine has rendered to a texture the mutex on the texture is released and signal is generated.

            The consumer (the host app) can take the texture for reading and sample from it while rendering it some view.

            1 Reply Last reply
            0

            1/5

            13 Mar 2024, 17:56

            • Login

            • Login or register to search.
            1 out of 5
            • First post
              1/5
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved