美文网首页程序员iOS随手分享
将U3d工程嵌入iOS工程中

将U3d工程嵌入iOS工程中

作者: 朝雨晚风 | 来源:发表于2016-10-23 18:07 被阅读2283次

    我的另外一篇将成型的iOS工程嵌入到u3d工程中

    一 、运行环境

    Unity 5.3.4
    Xcode 7.3

    二、 配置Unity中的iOS选项:

    2.png 1.png

    Auto Graphic API: 去掉勾,然后选择OpenGLES2
    Scripting Backend: IL2CPP
    Target Device:iPhone +ipad
    Target iOS Version: 8.0

    三、 Unity和iOS的结合

    屏幕快照 2016-10-23 下午5.17.01.png

    第一个就是我们自己的原生工程,第二个是Unity导出的iOS工程。

    五、开始整合文件

    1)把U3D中的 Classes、Data、Libraries、MapFileParser.sh 文件先粘贴到iOSNative工程的根目录下


    屏幕快照 2016-10-23 下午5.20.28.png

    (2)注意这里几个文件的添加方式,如果添加方式错误了,会导致整合的彻底失败

    Classes、Libraries、MapFileParser.sh 通过Add 添加到项目中,注意(选择Copy items if need 选择 Create groups)
    Data添加到项目中 (选择Copy items if needs,选中 Create folder references)

    3.png 屏幕快照 2016-10-23 下午5.23.22.png

    3)添加FrameWork

    下面的这些都需要添加到iOS 原生工程中去。
    注意:libiconv.2.dylib 这个的添加方法
    Add other 然后全局搜索 command+shift+G 然后输入/usr/lib 查找就可以了

    4.jpeg

    六、系统环境配置

    1)添加runScript

    5.jpeg

    2)添加头文件引用和库文件运用

    屏幕快照 2016-10-23 下午5.31.59.png
    屏幕快照 2016-10-23 下午5.32.12.png

    3) Project->MyProject->Build Setting
    在Other Linker Flags添加
    -lc++
    -weak_framework
    CoreMotion
    -weak-lSystem
    -Wl,-undefined,dynamic_lookup

    屏幕快照 2016-10-23 下午5.34.52.png

    在Other C Flags、Other C++ Flags添加
    -DINIT_SCRIPTING_BACKEND=1

    9.jpeg

    设置 C Language Dialekt:C99[-std=c99]
    设置 C++ Language Dialekt : C++ 11[-std=C++11]
    设置 C++ Standard Library : libc++ (LLVM C++ standard Library with C++11 support)
    设置 Enable Bitcode : NO

    屏幕快照 2016-10-23 下午5.38.13.png

    4). Project->MyProject->Build Setting
    点击如下图的“+”号,选择4个Add User-Defined Setting
    设置key值:GCC_THUMB_SUPPORT,设置Value值:NO
    设置key值:GCC_USE_INDIRECT_FUNCTION_CALLS,设置Value值:NO
    设置key值:UNITY_RUNTIME_VERSION,设置Value值:5.3.4
    设置key值:UNITY_SCRIPTING_BACKEND,设置Value值: il2cpp


    8.jpeg

    5) 选择Info.plist

    添加key值:Unity_LoadingActivityIndicatorStyle,设置Value值:-1

    七、文件配置和修改

    (1)、在Supporting Files文件夹中创建新的PCH文件,命名为PrefixHeader,如下图所示勾选上Target,将Classes中的Prefix.pch文件的内容全部拷贝到Supporting Files中的PrefixHeader.pch中。
    在Project->MyProject->Build Setting 设置Precompile Prefix Header: YES
    并在Prefix Header中添加: $(SRCROOT)/ARHere/PrefixHeader.pch

    6.jpeg

    (2)、将Classes/main.mm全部内容复制到iOS的main.m 并把iOS中的main扩展名改为.mm, 修改如下代码

    然后要删除Classes/main.mm文件 ,在iOS的main.mm中做如下修改


    10.jpeg

    (3)、AppDelegate的修改

    #import <UIKit/UIKit.h>
    #import "UnityAppController.h"
    @interface AppDelegate : UIResponder <UIApplicationDelegate>
    @property (strong, nonatomic) UIWindow *window;
    @property (strong, nonatomic) UIWindow *unityWindow;
    @property (strong, nonatomic) UnityAppController *unityController;
    - (void)showUnityWindow;
    - (void)hideUnityWindow;
    @end
    
    
    #import "AppDelegate.h"
    #import "ViewController.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    -(UIWindow *)unityWindow{
        
        return  UnityGetMainWindow();
    }
    
    -(void)showUnityWindow{
        
        [self.unityWindow makeKeyAndVisible];
    }
    
    -(void)hideUnityWindow{
        
        [self.window makeKeyAndVisible];
    }
    
    
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        
        _unityController = [[UnityAppController alloc] init];
        [_unityController application:application didFinishLaunchingWithOptions:launchOptions];
        
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.backgroundColor = [UIColor whiteColor];
        
        
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
        self.window.rootViewController = nav;
        
        
        [self.window makeKeyAndVisible];
        
        
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        
        [_unityController applicationWillResignActive:application];
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        
        [_unityController applicationDidEnterBackground:application];
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
        
        [_unityController applicationWillEnterForeground:application];
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        
        [_unityController applicationDidBecomeActive:application];
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        
        [_unityController applicationWillTerminate:application];
    }
    
    @end
    
    

    (4)、UnityAppController中的修改

    #pragma once
    
    #import <QuartzCore/CADisplayLink.h>
    
    #include "PluginBase/RenderPluginDelegate.h"
    
    @class UnityView;
    @class DisplayConnection;
    
    @interface UnityAppController : NSObject<UIApplicationDelegate>
    {
        UnityView*          _unityView;
        CADisplayLink*      _displayLink;
    
        UIWindow*           _window;
        UIView*             _rootView;
        UIViewController*   _rootController;
        UIView*             _snapshotView;
    
        DisplayConnection*  _mainDisplay;
    
        // we will cache view controllers for fixed orientation
        // auto-rotation view contoller goes to index=0
        //  UnityViewControllerBase* _viewControllerForOrientation[5];
        UIViewController* _viewControllerForOrientation[5];      //这里修改了。
    #if !UNITY_TVOS
        UIInterfaceOrientation  _curOrientation;
    #endif
    
        id<RenderPluginDelegate>    _renderDelegate;
    }
    
    // override it to add your render plugin delegate
    - (void)shouldAttachRenderDelegate;
    
    // this one is called at the very end of didFinishLaunchingWithOptions:
    // after views have been created but before initing engine itself
    // override it to register plugins, tweak UI etc
    - (void)preStartUnity;
    
    // this one is called at first applicationDidBecomeActive
    // NB: it will be started with delay 0, so it will run on next run loop iteration
    // this is done to make sure that activity indicator animation starts before blocking loading
    - (void)startUnity:(UIApplication*)application;
    
    // this is a part of UIApplicationDelegate protocol starting with ios5
    // setter will be generated empty
    @property (retain, nonatomic) UIWindow* window;
    
    @property (readonly, copy, nonatomic) UnityView*            unityView;
    @property (readonly, copy, nonatomic) CADisplayLink*        unityDisplayLink;
    
    @property (readonly, copy, nonatomic) UIView*               rootView;
    @property (readonly, copy, nonatomic) UIViewController*     rootViewController;
    @property (readonly, copy, nonatomic) DisplayConnection*    mainDisplay;
    
    #if !UNITY_TVOS
    @property (readonly, nonatomic) UIInterfaceOrientation      interfaceOrientation;
    #endif
    
    @property (nonatomic, retain) id                            renderDelegate;
    @property (nonatomic, copy)                                 void(^quitHandler)();
    
    @end
    
    // Put this into mm file with your subclass implementation
    // pass subclass name to define
    
    #define IMPL_APP_CONTROLLER_SUBCLASS(ClassName) \
    @interface ClassName(OverrideAppDelegate)       \
    {                                               \
    }                                               \
    +(void)load;                                    \
    @end                                            \
    @implementation ClassName(OverrideAppDelegate)  \
    +(void)load                                     \
    {                                               \
        extern const char* AppControllerClassName;  \
        AppControllerClassName = #ClassName;        \
    }                                               \
    @end                                            \
    
    //inline UnityAppController*    GetAppController()
    //{
    //  return (UnityAppController*)[UIApplication sharedApplication].delegate;
    //}
    // 这里也修改了
    #import "AppDelegate.h"
    inline UnityAppController*  GetAppController()
    {
        AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        return delegate.unityController;
    
    }
    
    
    #define APP_CONTROLLER_RENDER_PLUGIN_METHOD(method)                         \
    do {                                                                        \
        id<RenderPluginDelegate> delegate = GetAppController().renderDelegate;  \
        if([delegate respondsToSelector:@selector(method)])                     \
            [delegate method];                                                  \
    } while(0)
    
    #define APP_CONTROLLER_RENDER_PLUGIN_METHOD_ARG(method, arg)                \
    do {                                                                        \
        id<RenderPluginDelegate> delegate = GetAppController().renderDelegate;  \
        if([delegate respondsToSelector:@selector(method:)])                    \
            [delegate method:arg];                                              \
    } while(0)
    
    
    
    // these are simple wrappers about ios api, added for convenience
    void AppController_SendNotification(NSString* name);
    void AppController_SendNotificationWithArg(NSString* name, id arg);
    
    void AppController_SendUnityViewControllerNotification(NSString* name);
    
    
    屏幕快照 2016-10-23 下午6.02.57.png
    屏幕快照 2016-10-23 下午6.03.17.png

    (5)、删除Main.storyboard
    移除Main interface中的默认Main

    八、启动和隐藏U3d界面

    
    #import "ViewController.h"
    #import "AppDelegate.h"
    @interface ViewController ()
    @property(strong, nonatomic) UIButton *Btn;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        _Btn = [[UIButton alloc]initWithFrame:CGRectMake(40, 200, 80, 70)];
        _Btn.backgroundColor = [UIColor cyanColor];
        [_Btn setTitle:@"开启" forState:UIControlStateNormal];
        [_Btn addTarget:self action:@selector(go) forControlEvents:UIControlEventTouchDown];
        [self.view addSubview:_Btn];
    }
    
    -(void)go{
        
        //进入unity界面
        [(AppDelegate *)[UIApplication sharedApplication].delegate showUnityWindow];
        UnityPause(false);
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    
    

    相关文章

      网友评论

      • jianshu小赵:为啥按照你的法子 什么文件都没编译到(自然编译不会失败) 但是build PHasese 里面一个文件都没链接到 用的是xcode9
      • 朝雨晚风:其实个人不推荐用着篇文章的合并方法,这个反过来更简单些 将成型的iOS工程嵌入到u3d工程中
        http://www.jianshu.com/p/5292d6daeb54
        朝雨晚风:@jianshu小赵 ,再次合并只需要把最新的U3d工程的class、data、Library替换掉就好了(当然如果你在UnityAppController.mm做了修改,那就先替换这个文件啦)
        2、如果合并不成功,各种系统报错,搞了一会没搞定,那就建议你重新合并一遍吧,不用太纠结啦,花不了多少时间的。
        jianshu小赵:如果用第二种方法 岂不是 每次更新unity的 代码 都得 合并一次 反客为主的节奏
        James_Feng:虽然还是遇到一些小坑,不过这片文章说的方法步骤是比较简洁明了有效的。:+1:
      • 伪装v5:我只想问,,有没有demo,,我搞了两个天了,,都没配置出来。。我擦
        2a434e7c4f0f:@朝雨晚风 没办法 要求是这么个要求,现在又变成新问题了 no such file or directory: 'Coremotion' 真的是醉, 在other c++ flags 加不加Coremotion 都会报这个错 做的要吐血了
        朝雨晚风:@铠甲芯 其实这种方法太麻烦了,很容易出错,一般都是反过来将 iOS 工程集成进打包出的 xcode 工程中会更加简单点
        2a434e7c4f0f:我4天了,一直报错 在.pch里面报 could not build module "foundation" 网上的方法也没什么效果
      • 忘记密码的七:楼主unity和ios都会吗?能帮看看下面这个问题吗,不知道是什么原因引起的这个报错
        #0 il2cpp::vm::MetadataCache::Initialize()
        #1 il2cpp::vm::Runtime::Init(char const*, char const*)
        #2 ::InitializeIl2CppFromMain()
        #3 ::UnityInitApplicationNoGraphics()
        #4 ::-[UnityAppController application:didFinishLaunchingWithOptions:](UIApplication *, NSDictionary *)
        #5 ::-[AppDelegate application:didFinishLaunchingWithOptions:](UIApplication *, NSDictionary *)
        报:Thread 1:EXC_BAD_ACCESS(code=1,address=0×.......)
        万分感谢~~~~
      • paintingStyle:能加下你的联系方式吗 运行错误
      • ZDY360:请问第六步的(2)是在哪配置的
      • 6054a4da381e:很不错,很详细。我新建个工程可以编译成功
        伪装v5:能不能发个demo来看看
      • 贝灬小晖:环境还是配不起来,,.
      • 608fc5d5dc53:你好作者,公司要做VR项目。可是开发U3D开发人员导入的ios文件中#include "il2cpp-config.h"的NORETURN static void il2cpp_codegen_raise_exception (Il2CppCodeGenException *ex)
        {
        il2cpp::vm::Exception::Raise ((Il2CppException*)ex);显示错误,请教一下是什么原因。
        51米阳光:哈哈 你把那句屏蔽掉应该就可以了

      本文标题:将U3d工程嵌入iOS工程中

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