美文网首页iOS-swiftiOS开发记录Unity技术分享
最新iOS 整合Unity(xCode9.1 Swift4.0

最新iOS 整合Unity(xCode9.1 Swift4.0

作者: 与之书 | 来源:发表于2017-10-10 15:15 被阅读1442次

0

  1. xCode9.0才支持swift4.0,但是9.0有一个bug,拖入的第三方库不会自动编译,详见XCode9 拖入文件 不自动添加 compile sources 所以使用9.1beta版本
    2.beta版每次添加framework要选两次才有用,暂时没有解决方法,官方也没有版本更新
    3.准备好一个xCode9.1和一个正常导出的Unity工程

Unity 工程导出时区分模拟器和真机,只能在对应设备运行,如果使用了AR,只能在真机上运行。
先单独运行下unity项目,模拟器版本会报UnityMetalSupport.h中有重复定义,直接注释报错代码即可,真机运行不报这个错误,然后能正常运行即可进行整合工作

1、新建工程

> 1.1 xCode9新建工程都是面向iOS11的,如果要兼容低版本系统,比如8.0,需要手动选择。
并且在LaunchScreen和main storyboard设置中去掉“Use Safe Area Layout Guides”(safe area 只支持9.0以后)
02safeArea.png

> 1.2 将Unity目录和工程目录放在同一文件夹内


01目录结构.png

> 1.3 右键——>创建Group without floder
(xCode9创建group新增了同时建立文件夹的选项,这里选择不建立文件夹)
命名为Unity(任意命名)

2、拖入Unity相关文件 放在新建的Unity Group下

classes和libraries  不copy 创建group
data    不copy 创建reference
raw 下的Vuforia和qcar也要放在根目录 同样选择reference
拖入交接文件和配置文件(也可以手动创建) 
最终目录见第四点添加配置图   

3、 桥接文件和配置文件

3.1 配置文件MyUnity.xcconfig
//
//  Created by 空橙记 on 2017/9/30.

GCC_THUMB_SUPPORT = NO
GCC_USE_INDIRECT_FUNCTION_CALLS = NO
// 版本号要改成对应
UNITY_RUNTIME_VERSION = 5.3.4f1
UNITY_SCRIPTING_BACKEND = il2cpp

CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES
CLANG_WARN_OBJC_ROOT_CLASS = YES

CLANG_CXX_LANGUAGE_STANDARD = c++0x
CLANG_CXX_LIBRARY = libc++
GCC_ENABLE_CPP_EXCEPTIONS = YES
GCC_C_LANGUAGE_STANDARD = c99
OTHER_CFLAGS = -DINIT_SCRIPTING_BACKEND=1
GCC_DYNAMIC_NO_PIC = NO
OTHER_LDFLAGS = -weak_framework CoreMotion -weak-lSystem
ENABLE_BITCODE = NO

// 要手动添加framework  头文件路径  库文件路径
//GCC_PREFIX_HEADER = $(UNITY_IOS_EXPORT_PATH)/Classes/Prefix.pch;

//改成自己对应的路径 导出的Unity路径
UNITY_IOS_EXPORT_PATH = /Users/xhvr/SWIFT/UnityMonis

a.事实上所有的setting都可以在这里设置,比如framework,也可以手动添加到OTHER_LDFLAGS中,头文件、库文件路径类似,但不是很推荐这么做
b.之前将所有framework都写在OTHER_LDFLAGS中,报了个错,Stack Overflow上说,又时候顺序也会造成link问题
c.另一个原因是不直观,例如再要引入地图、分享或者其他功能时,不知道哪些已经添加过,哪些没有添加
d.而像头文件路径、库文件路径,不同的Unity项目导出时文件夹有所不同,有些有plugins文件夹有些没有,手动加会直观些
f.如果觉得麻烦,自己的一些内容又是固定的,可以在Build Setting中设置好,直接command+c复制,command+v粘贴在config文件中,自己保存起来重复使用。

如果之前已经对某些配置做了修改,再配置config文件的话,并不会覆盖,所以比如使用百度地图, other linker flags 添加了-ObjC,那么config文件里配置不生效,需要删除-ObjC,此时配置会生效,再在最后加上-ObjC
如果出现RegisterAllClasses() in RegisterMonoModules.o 的报错,看看other c flags是不是添加了 -DINIT_SCRIPTING_BACKEND=1

3.2 UnityBridge.h 文件
#ifndef UnityBridge_h
#define UnityBridge_h

#import <UIKit/UIKit.h>
#import "UnityUtils.h"
#import "UnityAppController.h"
#import "UnityInterface.h"
#endif /* UnityBridge_h */
3.3 UnityUtils.h 文件 (添加了一个初始化方法)
#ifndef UnityUtils_h
#define UnityUtils_h
void unity_init(int argc, char* argv[]);
#endif /* UnityUtils_h */
3.4 UnityUtils.mm 文件
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include <csignal>
#import <UIKit/UIKit.h>

static const int constsection = 0;
void UnityInitTrampoline();

extern "C" void unity_init(int argc, char* argv[])
{
    @autoreleasepool
    {
        UnityInitTrampoline();
// Unity版本不同,有些可能要选UnityInitRuntime的方法
//        UnityInitRuntime(argc, argv);
        UnityParseCommandLine(argc, argv);
        
        RegisterMonoModules();
        NSLog(@"-> registered mono modules %p\n", &constsection);
        RegisterFeatures();
        std::signal(SIGPIPE, SIG_IGN);
    }
}

以上有报错不用管,先放着
设置Objective-C Bridging Header 为UnityBridge.h文件

06桥接bridge.png

4、修改配置

info处添加MyUnity.xcconfig

03添加配置.png
设置Unity文件夹路径
04Unity文件夹路径.png
设置prefix文件路径
07prefix.png
添加头文件路径和库文件路径
08头文件.png
09库文件.png

添加framework

10framework.png

路径都是可以直接拖的
framework的bug上面说过,就是要选两次

5、创建main.swift

内容如下

import Foundation
import UIKit
// 这个方法名要和UnityUtils中的相同
unity_init(CommandLine.argc, CommandLine.unsafeArgv)
UIApplicationMain(
    CommandLine.argc,
    UnsafeMutableRawPointer(CommandLine.unsafeArgv)
        .bindMemory(
            to: UnsafeMutablePointer<Int8>.self,
            capacity: Int(CommandLine.argc)),
    nil,
    NSStringFromClass(AppDelegate.self)
)

注释Appdelegate.swift中的 @UIApplicationMain

6、其他文件修改

  1. 找到Unity中的main.mm文件,注释main方法
  1. 在UnityAppController.h中替换inline方法
//替换为此方法
NS_INLINE UnityAppController* GetAppController()
{
    NSObject<UIApplicationDelegate>* delegate = [UIApplication sharedApplication].delegate;
    // 这里的@字符串 要和Appdelegate.swift中的变量名一致
    UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"unityController"];
    return currentUnityController;
}
  1. 修改AppDelegate
//@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var unityController: UnityAppController?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        unityController = UnityAppController()
        unityController?.application(application, didFinishLaunchingWithOptions: launchOptions)
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        unityController?.applicationWillResignActive(application)
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        unityController?.applicationDidEnterBackground(application)
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
        unityController?.applicationWillEnterForeground(application)
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        unityController?.applicationDidBecomeActive(application)
    }
    
    func applicationWillTerminate(_ application: UIApplication) {
        unityController?.applicationWillTerminate(application)
    }
}

7.使用

创建一个新的ViewController 或者在ViewController中也可以
使用AR需要添加相机权限
在viewDidLoad()中直接添加
self.view.addSubView(UnityGetGLView())
如果不要全屏,可以手动设置frame

8.bug

在buildSetting中设置swift版本如果是3.2,能正常运行没有任何问题,如果设置4.0会报
valueForUndefinedKey的错误。解决很简单,在appdelegate中加上@objc 即可
    @objc var unityController: UnityAppController?

如果Unity版本比较低,可能会遇到xxx was compiled with optimization - stepping may behave oddly; variables may not be available的问题,请在building setting-> Other C Flags 中添加:-DRUNTIME_IL2CPP=1,前面加的也要保留。然后把Optimization Level ,debug的部分都改成none。
参考: https://stackoverflow.com/questions/45078851/optimization-stepping-may-behave-oddly-ios-unity

参考:童冀的2.3融合教程
swift3.0融合Unity
的一部分内容,不过还是得说一下,原文中很多步骤是不需要的,例如添加脚本、例如main.mm中main方法的替换(直接注释即可,参见下面matt_eaton博客内容)。而有些方法已经不适用,例如main.swift中的UIApplicationMain方法,原文中的会报错。
blitzagency的教程以及一些文件
matt_eaton 的一篇博客
swift4.0 整合Unity报错问题

内容不算很难,但是xCode9的坑有点多,尤其不能自动编译第三方库,测试了好久。然后9.1的framework添加两次。。。以及safe area设置等等,在整合前花了太多时间处理IDE的问题。

参照阅读之前写的xCode8.3 + OC +Unity教程
对照一下,可以理解得更清楚一些。

如果文章有所帮助,欢迎打赏😄


😄.png

相关文章

网友评论

  • 起个名字好难O0:UnityUtils这三个文件是哪来的? 自己创建的吗
    与之书:@起个名字好难O0 这个太久没有接触了 当时只是临时做的一个ios项目 正常来说这个方法应该是没问题的 如果是找不到方法 把上面的步骤每一步再对一下 或者看看swift的版本,如果报了其他错,暂时想不到什么信息
    起个名字好难O0:@与之书 UnitUtils.h里面的方法是void unity_init(int argc, char* argv[]); 然后自己新建的main.swift里面不管是用custom_unity_init(CommandLine.argc, CommandLine.unsafeArgv) 还是unity_init(CommandLine.argc, CommandLine.unsafeArgv) 都会报错
    与之书:@起个名字好难O0 是的
  • 79292ce48ab6:请问楼主有遇到过真机运行崩溃的问题么?我按照你的教程接进去了,然后在运行的时候崩在UnityAppController.mm文件中的UnityInitApplicationNoGraphics这个方法处。
    79292ce48ab6:@与之书 我已经解决了,谢谢你的回复。
    与之书:@Ht黄涛先生 很久没接触了……看看日志具体报什么错吧
  • ebfedff14320:您好
    在製作畢業專題的專案上
    我按照您的步驟全部做完後
    在“3.4 UnityUtils.mm 文件”這個步驟中,
    添加的這行
    UnityParseCommandLine(argc, argv);
    會報錯(Use of undeclared identifier 'UnityParseCommandLine'),
    後面也按照指示
    設置了Objective-C Bridging Header
    還是一樣。

    如果我把這行註解掉
    會出現錯誤
    clang: error: no such file or directory: 'CoreMotion'
    不知道怎麼解決..

    //我的 Unity 專案沒有用到 AR
    //但是有類似一樣要開相機的功能
    //另外 mac 上的 Unity 版本是 〃2017.2.0f3 〃這個好像差異滿大的@@?
    //版本號也有在 MyUnity.xcconfig 中有改掉

    希望您能在繁忙之中抽空幫忙解答謝謝><
    与之书:@虎_e459 也可能是头文件没有正确引用的问题 可以全局搜一下这个方法看下在Unity的哪个文件中,确认下是否导入正确。 头文件和库文件的导入上文也有说 也可以对照oc语言的整合看下是否有遗漏
    与之书:手头没有设备可以测试(项目使用以前公司的mac mini做的)。找不到UnityParseCommandLine这份方法的问题我没有碰到过,后面配置好之后,报错就消失了。main.mm中的main方法有注释掉么? Unity版本差别挺大的,不过看起来2017应该也不会是太旧的版本。据说早期的版本应该用UnityInitRuntime(argc, argv);(就是文中注释掉的方法),如果不行的话,看看链接blitzagency的教程,看看有没有帮助。
    ebfedff14320:另外
    在 ViewController.swift(原始的)添加的這行
    self.view.addSubView(UnityGetGLView())
    也會報錯(Value of type 'UIView' has no member 'addSubView')
    後來去查了一下addSubView改成addSubview就好了(?
    不過剛剛上面的問題還是沒解決orz
  • YDomo:你好,我是个人版unity 导入xcode项目时候,只是导出一个空的文件夹,请问是什么问题
    与之书:嗯? Unity导出是空的? 如果是Unity的部分,我可能解答不了,直接是别人给的。

本文标题:最新iOS 整合Unity(xCode9.1 Swift4.0

本文链接:https://www.haomeiwen.com/subject/mhivyxtx.html