Skip to content

How to run unity game from iOS app

Setup

  • Create unity project with any custom settings
  • If running in iOS simulator
    • change the Target SDK under player settings to Simulator SDK
  • Create build for iOS
  • Create a new swift UI app from xcode
    • Run it to check if it works fine without any errors
  • Create a new workspace from xcode
    • Open workspace
    • Right click on the left project navigation panel and click add files to <workspace-name>
    • Choose Unity-iPhone.xcodeproj from the unity build folder which we created earlier and select create groups for any added folders
    • Choose <swift-ui-app>.xcodeproj from the swift UI app folder which we created earlier and select create groups for any added folders
    • Now, we have both unity build and iOS app together in the xcode workspace

Integrate unity app with swift UI

  • Add UnityFramework.framework in iOS app target. It is under Targets > General > Frameworks, Libraries, and Embedded Contenta

  • Add Data folder to UnityFramwork. Select Data folder under the Unity project and on the right side panel, check the UnityFramework checkbox under Target Membership

  • Add a new swift class to iOS project

    • Paste this below code inside that file
    swift
    import Foundation
    import UnityFramework
    
    class Unity: UIResponder, UIApplicationDelegate {
    
        static let shared = Unity()
    
        private let dataBundleId: String = "com.unity3d.framework"
        private let frameworkPath: String = "/Frameworks/UnityFramework.framework"
    
        private var ufw : UnityFramework?
        private var hostMainWindow : UIWindow?
    
        private var isInitialized: Bool {
            ufw?.appController() != nil
        }
    
        func show() {
            if isInitialized {
                showWindow()
            } else {
                initWindow()
            }
        }
    
        func setHostMainWindow(_ hostMainWindow: UIWindow?) {
            self.hostMainWindow = hostMainWindow
        }
    
        private func initWindow() {
            if isInitialized {
                showWindow()
                return
            }
    
            guard let ufw = loadUnityFramework() else {
                print("ERROR: Not able to load Unity")
                return unloadWindow()
            }
    
            self.ufw = ufw
            ufw.setDataBundleId(dataBundleId)
            ufw.register(self)
            ufw.runEmbedded(
                withArgc: CommandLine.argc,
                argv: CommandLine.unsafeArgv,
                appLaunchOpts: nil
            )
        }
    
        private func showWindow() {
            if isInitialized {
                ufw?.showUnityWindow()
            }
        }
    
        private func unloadWindow() {
            if isInitialized {
                ufw?.unloadApplication()
            }
        }
    
        private func loadUnityFramework() -> UnityFramework? {
            let bundlePath: String = Bundle.main.bundlePath + frameworkPath
    
            let bundle = Bundle(path: bundlePath)
            if bundle?.isLoaded == false {
                bundle?.load()
            }
    
            let ufw = bundle?.principalClass?.getInstance()
            if ufw?.appController() == nil {
                let machineHeader = UnsafeMutablePointer<MachHeader>.allocate(capacity: 1)
                machineHeader.pointee = _mh_execute_header
    
                ufw?.setExecuteHeader(machineHeader)
            }
            return ufw
        }
    }
    
    extension Unity: UnityFrameworkListener {
    
        func unityDidUnload(_ notification: Notification!) {
            ufw?.unregisterFrameworkListener(self)
            ufw = nil
            hostMainWindow?.makeKeyAndVisible()
        }
    }
    • Replace ContentView.swift file with this below code
    swift
    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
                Button(action: {                        
                    Unity.shared.show()
                    }) {
                        Text("Launch Unity")
                    }
            }
            .padding()
        }
    }
    
    #Preview {
        ContentView()
    }
  • Run the iOS target, that's all.

  • Unity game should launch now by clicking the Launch Unity text in the iOS app.