# 原生iOS项目集成Unity3D项目

2,484 阅读3分钟

集成步骤

准备

  1. swift 4.1
  2. Xcode 9.3
  3. Unity 2018.1.1f1

开始集成

说明:

  1. 已经存在 swiftObjective-C 的桥接头文件

  2. 使用了cocoapods 并且已经执行了 pod install

  3. 原生项目是竖屏,而 Unity3D 需要横屏

  4. Unity3D 导出 Xcode 工程 Player Settings 的设置:

  • OrientationDefault Orientation改为Auto Rotation
  • Splash ImageSplash ScreenLogos 均不勾选
  • Other SettingsTarget Device 改为 iPhone OnlyTarget SDK 改为 Device SDKTarget minimum iOS version 改为 8.0,Architecture 改为 ARM64
  1. 在原生项目中新建 Unity 文件夹,放在工程代码的同级目录即可,并进行下列操作

    1. 下载 blitzagency的教程以及一些文件
    2. 把刚才下载的文件夹中的 Unity.xcconfigUnityBridge.hUnityUtils.hUnityUtils.mm 这4个文件拉进刚才创建的文件夹 Unity 中,拉的时候会提示创建桥接文件,选择不创建
    3. 修改 Unity.xcconfig 文件的配置
    // 如果使用了 `cocoapods` 需要引入 `cocoapods.xcconfig` 文件
    #include "Pods/Target Support Files/Pods-XHStudent_ECoach/Pods-XHStudent_ECoach.debug.xcconfig"
    #include "Pods/Target Support Files/Pods-XHStudent_ECoach/Pods-XHStudent_ECoach.release.xcconfig"
    
    UNITY_SCRIPTING_BACKEND = il2cpp;
    GCC_PREFIX_HEADER = $(PRODUCT_NAME)/Unity/Classes/Prefix.pch;
    
    HEADER_SEARCH_PATHS = $(inherited) "$(PRODUCT_NAME)/Unity/Classes" "$(PRODUCT_NAME)/Unity/Classes/Unity" "$(PRODUCT_NAME)/Unity/Classes/Native" "$(PRODUCT_NAME)/Unity/Libraries" "$(PRODUCT_NAME)/Unity/Libraries/libil2cpp/include" ${PODS_HEADER_PATHS};
    
    LIBRARY_SEARCH_PATHS = $(inherited) "$(PRODUCT_NAME)/Unity/Libraries" "$(PRODUCT_NAME)/Unity/Libraries/libil2cpp/include" ${PODS_LIBRARY_PATHS};
    
    OTHER_CFLAGS = $(inherited) -DINIT_SCRIPTING_BACKEND=1 -fno-strict-overflow -DRUNTIME_IL2CPP=1;
    
    OTHER_LDFLAGS = $(inherited) -weak-lSystem -weak_framework CoreMotion -weak_framework GameKit -weak_framework iAd -framework AVFoundation -framework AudioToolbox -framework CFNetwork -framework CoreGraphics -framework CoreLocation -framework CoreMedia -framework CoreVideo -framework Foundation -framework MediaPlayer -framework MediaToolbox -framework Metal -framework OpenAL -framework OpenGLES -framework QuartzCore -framework SystemConfiguration -framework UIKit -liconv.2 -liPhone-lib -lil2cpp ${PODS_LIBRARIES};
    
    SWIFT_OBJC_BRIDGING_HEADER = $(PRODUCT_NAME)/Bridge/XHStudent_ECoach-Bridging-Header.h;
    SWIFT_PRECOMPILE_BRIDGING_HEADER = YES;
    
    1. 修改工程配置,使用 Unity.xcconfig 点击 PROJECT -> Info -> Configuration,将 project 设置为 Unity.xcconfig,下面对应的 target 改为相应的 cocoapods.xcconfig 即可
    2. 修改buildSetting配置,路径和你unity的版本号
      1. 点击 target -> Build Settings
      2. 点击搜索 UNITY_IOS_EXPORT_PATH, 设置为你第一步中导出 Xcode 的位置,
      3. UNITY_RUNTIME_VERSION 设置为对应的 Unity2018.1.1f1) 版本
      4. Enable bitcode,设置为 NO
    3. build Phases 中添加运行脚本
      echo "Syncing data from + $UNITY_IOS_EXPORT_PATH..."
      
      rm -rf "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data"
      
      cp -Rf "$UNITY_IOS_EXPORT_PATH/Data" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Data"
      
    4. Unity3D 导出的文件夹 ClassesLibraries 放入 Unity 文件夹
    5. 增加 main.swift 文件
    custom_unity_init(CommandLine.argc, CommandLine.unsafeArgv)
    

UIApplicationMain( CommandLine.argc, UnsafeMutableRawPointer(CommandLine.unsafeArgv) .bindMemory( to: UnsafeMutablePointer.self, capacity: Int(CommandLine.argc)), nil, NSStringFromClass(AppDelegate.self) ) 9. 修改导入的文件 1. 将 `main.mm` 中的 `main` 改为 `old_main` 2. 替换 `UnityAppController` 中的 `GetAppController` 方法 //注释此方法 //inline UnityAppController* GetAppController() //{ // return (UnityAppController*)[UIApplication sharedApplication].delegate; //}

    //替换为此方法
    NS_INLINE UnityAppController* GetAppController()
    {
        NSObject<UIApplicationDelegate>* delegate = [UIApplication sharedApplication].delegate;
        UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"currentUnityController"];
        return currentUnityController;
    }
    ```
10. 修改原生项目
    1. 注释 `@UIApplicationMain`,按图添加部分代码

集成错误及解决方式

  1. 集成了 ZBar 点击 target -> Build Phases 搜索 EZCodeSCannerViewController.mm,在 Compiler Flags 中设置 -fno-objc-arc 修改 EZCodeSCannerViewController.mm 中的 UITextAlignmentCenterNSTextAlignmentCenter

  2. 原生项目为竖屏,Unity3D 模块为横屏

    class UnityViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            
            appDelegate.blockRotation = true
            UnityGetGLView().frame = view.frame;
            view.addSubview(UnityGetGLView())
            view.setNeedsLayout()
        }
        
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            let value = UIInterfaceOrientation.landscapeLeft.rawValue
            UIDevice.current.setValue(value, forKey: "orientation")
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            appDelegate.blockRotation = false
            let value = UIInterfaceOrientation.portrait.rawValue
            UIDevice.current.setValue(value, forKey: "orientation")
        }
        
        override open var shouldAutorotate: Bool {
            return false
        }
        
        override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            return .landscapeLeft
        }
    }
    
  3. 原生与 Unity3D 交互 在 UnityUtils 扩展一个函数(两边的函数名必须一致,且不能使用系统预留关键字),然后在本地监听该能通知即可

    extern "C" void dismiss()
    {
        [[NSNotificationCenter defaultCenter] postNotificationName: @"dismiss" object:nil userInfo:nil];
    }
    

    Unity 则需要包含 System.Runtime.InteropServices

    //导出按钮以后将在xcode项目中生成这个按钮的注册,
    //这样就可以在xocde代码中实现这个按钮点击后的事件。
    [DllImport("__Internal")]
    private static extern void _PressButton0 ();
    
    public static void ActivateButton0 () {
        if (Application.platform != RuntimePlatform.OSXEditor)  {
            //点击按钮后调用xcode中的 _PressButton0 ()方法,
            //方法中的内容须要我们自己来添加
            _PressButton0 ();
        }
    }
    
  4. 单独的由 Unity 导出的 Xcode 的工程无法构建版本 需要添加访问权限才可以

    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>是否许允此App使用蓝牙?</string>
    <key>NSCalendarsUsageDescription</key>
    <string>是否允许此App使用日历?</string>
    <key>NSCameraUsageDescription</key>
    <string>我们需要通过您的相机扫描二维码等</string>
    <key>NSContactsUsageDescription</key>
    <string>是否允许此App访问你的通讯录?</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>我们需要通过您的地理位置信息获取您周边的驾校相关信息</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>是否允许此App使用你的麦克风?</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>我们需要通过你的相册获取二维码图片等</string>
    <key>NSSpeechRecognitionUsageDescription</key>
    <string>是否允许此App使用语音识别?</string>
    
  5. 会创建一个默认的 window,此 window 会默认放在第一个 如果有使用到系统默认的window时

    let window = ((UIApplication.shared.delegate?.window)!)!
    

参考网址

www.aliyun.com/jiaocheng/3… blog.csdn.net/zhao18933/a… www.jianshu.com/p/dc68baad8… www.jianshu.com/p/e8217896d… blog.csdn.net/studying_io… www.jianshu.com/p/fd52e2cf2… www.jianshu.com/p/7624a5d56… blog.csdn.net/scboyhj__/a… www.jianshu.com/p/f938a712d… www.jianshu.com/p/5c773628c… www.jianshu.com/p/07b86dc7c… www.cocoachina.com/bbs/read.ph… blog.csdn.net/yidu_blog/a… www.cocoachina.com/bbs/read.ph… www.mamicode.com/info-detail… www.cnblogs.com/sjxjjx/p/62…

sudo gem install cocoapods