I’m trying to integrate a Unity view in SwiftUI, I have the below code, but when I run the app I get no output, I know SpriteKit and SceneKit are possible and my unity view runs in a standard swift app, I’m wondering if swiftUI is possible.
struct ContentView: View {
var body: some View {
UnityUIView()
}
}
struct UnityUIView : UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
appDelegate.startUnity()
return UnityGetGLView()!
}
func updateUIView(_ view: UIView, context: Context) {
}
}
I've tried to create a UIViewControllerRepresentable but get the same thing, The screen flashes once and then disappears, I think it's the splash screen as I changed the colour for debugging, no dice.
struct ContentView: View {
var body: some View {
TestUnityViewController()
}
}
struct TestUnityViewController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let vc = UIViewController()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.startUnity()
let unityView = UnityGetGLView()!
vc.view.backgroundColor = .red
vc.view!.addSubview(unityView)
return vc
}
func updateUIViewController(_ viewController: UIViewController, context: Context) {
}
}
If I add a delay to the UIViewControllerRepresentable, it works....interesting
struct TestUnityViewController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let vc = UIViewController()
vc.view.backgroundColor = .red
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.startUnity()
let unityView = UnityGetGLView()!
vc.view!.addSubview(unityView)
}
return vc
}
func updateUIViewController(_ viewController: UIViewController, context: Context) {
}
}
For people still having the issue. I haven't investigated yet, but if you are using the new Unity example to integrate Unity as a framework, the delay indeed fixed the issue with SwiftUI.
You can create a SwiftUI View to which the Unity view will be added:
import SwiftUI
struct TestUnityViewController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let vc = UIViewController()
UnityBridge.showUnity()
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
let unityView = UnityBridge.getAppController().rootView!
vc.view!.addSubview(unityView)
}
return vc
}
func updateUIViewController(_ viewController: UIViewController, context: Context) {}
}
struct ContentView: View {
var body: some View {
TestUnityViewController()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here, UnityBridge is a wrapper around the Unity framework instanciation, similar to the Objective C version from the repository.
The methods:
showUnity() creates the UnityFramework instance, and then calls the showUnityWindow methodgetAppController calls the appController method from he UnityFramework objectIn the meantime I find a better solution, this will do. I imagine there is a better way to do that, maybe an event triggered to know when Unity's view is fully ready.
EDIT:
I created an example repository to show how to integrate Unity in a SwiftUI project: https://github.com/DavidPeicho/unity-swiftui-example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With