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
Forum Updated to NodeBB v4.3 + New Features

Embeding Unity3D within Qt application

Scheduled Pinned Locked Moved Unsolved Qt for Python
5 Posts 4 Posters 933 Views 1 Watching
  • 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 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()'
    jsulmJ JonBJ 2 Replies Last reply
    0
    • SGaistS SGaist moved this topic from General and Desktop on
    • P Pythonic person

      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()'
      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on 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
      0
      • P Pythonic person

        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()'
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on 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
        • jsulmJ jsulm

          @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 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 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

            • Login

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