Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI and Unity

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) {

  }
}
like image 883
Chris Avatar asked Jan 19 '26 00:01

Chris


1 Answers

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 method
  • getAppController calls the appController method from he UnityFramework object

In 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

like image 51
David Peicho Avatar answered Jan 21 '26 14:01

David Peicho