iOS swift 与 unity交互踩坑(一)

314 阅读2分钟

一、集成unity image.png

  1. unity导出的iOS工程 2.编译成framework 把Data文件编译进framework中 image.png image.png comand+ B 切换到 framework 编译成framework image.png 如下图就是编译成功 image.png

  2. 集成到主项目中 在项目中根目录下新建文件夹 把framework放到里面 image.png 二、unity与swift相互传值

  3. unity 与 ios 交互 1.ios 传参数给unity

    1. 把unity编译成Framework 添加到 iOS主项目中 image.png 2.读取framework class UnityAppDelegateToolSwift: NSObject {

    static let shared = UnityAppDelegateToolSwift()

    private(set) var argc:Int32? private(set) var argv:UnsafeMutablePointer<UnsafeMutablePointer?>? private(set) var launchOptions: [UIApplication.LaunchOptionsKey: Any]?

    func configureLaunchParames(argc:Int32, argv:UnsafeMutablePointer<UnsafeMutablePointer?>,launchOptions:[UIApplication.LaunchOptionsKey:Any]?) { self.argc = argc self.argv = argv self.launchOptions = launchOptions }

    func getLaunchArgc() -> Int32? { guard let argc = self.argc else { return nil } return argc } func getLaunchArgv() -> UnsafeMutablePointer<UnsafeMutablePointer?>? { guard let argv = self.argv else { return nil } return argv }

    func getLaunchOptions() -> [UIApplication.LaunchOptionsKey: Any]? { guard let options = self.launchOptions else { return [:] } return options }

} UnityAppInstanceSwift 用来处理unityFramework交互逻辑 class UnityAppInstanceSwift: NSObject, UnityFrameworkListener {

static let shared = UnityAppInstanceSwift()

private var ufw:UnityFramework?

private var unityAppController:UnityAppController?
private var isFirstLoaded = true



func showUnityView()  {
    guard self.unityIsInitialied() else {
        DLog("初始化不成功")
        return
    }
    self.pause(isPause: false)
    if isFirstLoaded {
        self.ufw?.showUnityWindow()
    }else{
        restartUnityView()
    }
    
}

private func restartUnityView() { if let rootView = self.unityAppController?.rootView { rootView.isHidden = false rootView.alpha = 0 UIView.animate(withDuration: 0.25) { rootView.alpha = 1.0 self.ufw?.showUnityWindow() } } }

func showNativeView()  {
    
    guard let rootView = self.unityAppController?.rootView else { return  }
    UIView.animate(withDuration: 0.25) {
        rootView.alpha = 0
    } completion: {_ in 
        self.pause(isPause: true)
        rootView.isHidden = true
        self.removeAllSubViews(from: rootView)
        rootView.removeFromSuperview()
        appDelegate.window?.makeKeyAndVisible()
    }
}
private func removeAllSubViews(from parentView:UIView?){
    // 逆序遍历子视图并移除, 避免索引错位问题
    parentView?.subviews.reversed().forEach { subview in
        subview.removeFromSuperview()
    }
}

func initUnity() { if !self.unityIsInitialied() { DLog("===初始化不成功===") self.ufw = self.unityFrameworkLoad()

        guard let argc = UnityAppDelegateToolSwift.shared.getLaunchArgc() else { return  }
        guard let argv = UnityAppDelegateToolSwift.shared.getLaunchArgv() else { return  }
        guard let launchOption = UnityAppDelegateToolSwift.shared.getLaunchOptions() else { return  }
        DLog("====ufw===\(self.ufw)===argc===\(argc)===argv===\(argv)==argc===\(launchOption)")
        self.ufw?.runEmbedded(withArgc: argc, argv: argv, appLaunchOpts: launchOption)
        
        self.isFirstLoaded = true
    }else{
        self.isFirstLoaded = false
    }
   
    

}

func initUnityWithFrame(rect:CGRect) { appDelegate.allowRotation = 1 self.initUnity() self.unityAppController = self.ufw?.appController()

    let window = self.unityAppController?.window
    window?.frame = rect
}

func pause(isPause:Bool)  {
    guard let ufw = self.ufw else { return }
    ufw.pause(isPause)
}

// 发送消息给unity func sendMessageToGOWithName(goName:String, name:String, msg:String) { self.ufw?.sendMessageToGO(withName: (goName as NSString).utf8String, functionName: (name as NSString).utf8String, message: (msg as NSString).utf8String) }

func unityIsInitialied() -> Bool {
    return self.ufw != nil && self.unityAppController != nil
}

func unityFrameworkLoad() -> UnityFramework? {
    // 获取主 bundle 的路径
    // 构建 UnityFramework 的完整路径
    let bundlePath = Bundle.main.bundlePath.appending("/Frameworks/UnityFramework.framework")
    DLog("====unityFrameWork路径===\(bundlePath)====")
    // 使用指定的路径创建一个 NSBundle 对象
    guard let bundle = Bundle(path: bundlePath) else {
        return nil
    }
    
    // 如果 bundle 没有被加载,则加载它
    if !bundle.isLoaded {
         bundle.load()
    }

    // 获取 UnityFramework 的主类实例
    let ufw = bundle.principalClass?.getInstance()
    
    // 设置数据 bundle ID
    ufw?.setDataBundleId("com.unity3d.framework")

    return ufw
}

func superUnityView() -> UIView? { guard let unityAppController = self.unityAppController else { return nil } return unityAppController.rootViewController.view }

// 卸载unity
private func unloadUnityInternal() {
    if let unityFramework = self.ufw {
        unityFramework.unregisterFrameworkListener(self)
    }
    self.ufw = nil
}

// 监听
@objc func unityDidUnload(_ notification: Notification!) {
    unloadUnityInternal()
}


@objc func unityDidQuit(_ notification: Notification!) {
    unloadUnityInternal()
}

}

========AppDelegate============ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch.

   // 启动参数传给UnityFramework

UnityAppDelegateToolSwift.shared.configureLaunchParames(argc: CommandLine.argc, argv: CommandLine.unsafeArgv, launchOptions: launchOptions)

    return true
}

在unity界面处理相关逻辑 class UnityPlayerViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad()

    // Do any additional setup after loading the view.
    DLog("===宽度====\(currentWidth)===高度====\(currentHeight)====")
    UnityAppInstanceSwift.shared.initUnityWithFrame(rect: CGRectMake(0, 0, UIScreen.main.bounds.width, UIScreen.main.bounds.height))
    loadUI()
    loadUnityInfo()
}

// 加载模型 MainControl loadModel3D 都是与unity约定好的 func loadUnityInfo() {

    guard let carFileName = MapInfoManager.shared.model3DCarFileName else {
        XHProgressHUD.show(text: "车辆信息不存在")
        return
    }
    
    DLog("====车辆信息路径==\(carFileName)====")
    
    let localFilePath = 相对地址
    guard let localPath = localFilePath else { return  }
    let model3DCarFilePath = "\(localPath)/\(carFileName);\(carFileName)"
    UnityAppInstanceSwift.shared.sendMessageToGOWithName(goName: "MainControl", name: "loadModelCar3D", msg: model3DCarFilePath)
    
    guard let modelLineName = MapInfoManager.shared.model3DMapLineName else {
        XHProgressHUD.show(text: "地图信息不存在")
        return
    }
    UnityAppInstanceSwift.shared.sendMessageToGOWithName(goName: "MainControl", name: "loadModelMap3D", msg: model3DMapLinePath)
            
}   

}