Embeding Unity3D within Qt application
-
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:
-
S SGaist moved this topic from General and Desktop on
-
@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
-
@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.
-
@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? -
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.