iOS swift 与 unity交互踩坑(一)

一、集成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<Int8>?>?
    private(set) var launchOptions: [UIApplication.LaunchOptionsKey: Any]?

    func configureLaunchParames(argc:Int32, argv:UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>,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<Int8>?>? {
    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)
            
}   

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 最近在实验室做了一个项目,用到了蓝牙通讯和U3D的交互,都有很多坑,如:IOS与Unity3D界面之间的跳转...
    Larrycal阅读 23,804评论 34 53
  • iOS集成Unity 近年来iOS和Unity发展都非常迅速,而iOS和Unity都有各自擅长的领域,iOS在传统...
    为你写诗_d170阅读 3,570评论 0 0
  • 最近在弄一个iOS的嵌入统一的功能,大费脑细胞......各种坑,网上找了很多帖子方法,虽然我比较懒,很少整理发表...
    JeffreyTaiT阅读 12,503评论 2 10
  • 最近遇到一个识别图像后显示3D模型的需求,权衡再三选择了国内的easyAR SDK。Unity建模完成后,导出相应...
    Lotheve阅读 7,939评论 11 6
  • 基本思路: Xcode 工程创建工作空间,一个工作空间包含 iOS原生工程,一个为3D工程。通过UnityFram...
    Z小新阅读 9,506评论 1 3