ios调用unity3d

2016-07-04 18:56:28 huayu_huayu 阅读数 5767
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

1.unity3d调用ios

unity3d的c#脚本里写:

#if UNITY_IPHONE
  [DllImport("__Internal")]
  private static extern void btnAction(string title, string msg);
#endif


ios里写(最好appdelegate里,其他地方也可以):

extern "C" void btnAction(const char *title, const char *msg){
//这里写实现
}

2.ios调用unity3d

ios里写(任意类):

UnitySendMessage("Sun", "SearchTarget",[sendMsg UTF8String]);


参数意思:
Sun是一个物理对象,可以是Plane,club

SearchTarget是方法

sendMsg是要传输的数据

函数原型:

void UnitySendMessage(constchar* obj, constchar* method, constchar* msg);



unity3d的c#脚本里(要跟上面sun对象所运行的脚本里,其他脚本无效)写:

void SearchTarget(string message)
{
//这里写实现
}


参考链接:

http://www.tuicool.com/articles/Y7R3eyn

2016-06-07 23:12:00 weixin_30791095 阅读数 23
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

转自:http://www.cnblogs.com/alongu3d/p/3279277.html

我用的Unity3d 4.2版本,这一节说一下IOS与U3D的交互!

   首先在U3D中写个方法:这个时候导出为ios代码必须是真机,模拟器是无法调用的,转化为IOS代码后,可以看这里,

这个图只是说明我们定义的CallU3D()方法,但是返回值确并不是string类型,而是void我很奇怪,呵呵!

下面是实现这个方法,

这个实现方法写在.mm文件中就行,不一定非要在这个类中,也可以新建一个类,也行的!

下面我说一下,如何在U3D游戏窗口上添加视图,我是新建了一个视图,是一个按钮,

这个视图,调用这个方法

其中UnitySendMessage对应的是U3D中的,第一个参数是物体,第二个参数是方法,第三个参数是调用方法的参数!

最后截取个真机图!

 
 

转载于:https://www.cnblogs.com/feiyu-mdm/p/5568655.html

2017-05-03 09:53:23 xiaota00 阅读数 4272
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

第一部分:

第一部分:iOS传消息到Unity3d中。


1.

首先用Unity3d创建一个Plain,并调整好摄像机的角度以及光源的位置,如下所示:





2.

然后我们创建一个Cube,我们会在iOS中用Objective-C代码来控制它旋转:






3.

然后我们创建一个Rotate.js的脚本并把它关联到Cube上:

[javascript] view plain copy
  1. var vrotate : Vector3;    
  2.     
  3. //Rotate Left  
  4. function RotateLeft()    
  5. {  
  6.     print("Rotate Left");  
  7.     transform.Rotate(Vector3.up * Time.deltaTime * 100, Space.World);  
  8. }    
  9.     
  10. //Rotate Right  
  11. function RotateRight()    
  12. {  
  13.     print("Rotate Right");  
  14.     transform.Rotate(Vector3.down * Time.deltaTime * 100, Space.World);      
  15. }    
  16.     
  17. //Rotate Up  
  18. function RotateUp()  
  19. {  
  20.     print("Rotate Up");  
  21.     transform.Rotate(Vector3.right * Time.deltaTime * 100, Space.World);      
  22. }    
  23.     
  24. //Rotate Down  
  25. function RotateDown()  
  26. {  
  27.     print("Rotate Down");  
  28.     transform.Rotate(Vector3.left * Time.deltaTime * 100, Space.World);      
  29. }  

上面的四个函数分别朝不同角度选择Cube。我们会在iOS程序中调用这几个Unity3d中的函数。




4.

然后在Unity3d中Build为XCode项目,打开该项目。首先创建一个基于NSObject的类,名为MyViewInit,我们会将我们自己的界面初始化代码都放在其中。修改MyViewInit.h如下:

[cpp] view plain copy
  1. //  
  2. //  MyViewInit.h  
  3. //  Unity-iPhone  
  4. //  
  5. //  Created by tao hu on 9/15/12.  
  6. //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.  
  7. //  
  8.   
  9. #import <UIKit/UIKit.h>  
  10.   
  11. @interface MyViewInit : NSObject  
  12.   
  13.   
  14. +(void)CreateButton:title rect:(CGRect)rect action:(SEL)action controller:(UIViewController *)controller;  
  15. +(void)CreateTitle:(UIViewController *)controller;  
  16. +(void)LeftButtonPressed;  
  17. +(void)RightButtonPressed;    
  18. +(void)UpButtonPressed;  
  19. +(void)DownButtonPressed;  
  20. +(void)Init:(UIViewController *)controller;  
  21.   
  22.   
  23. @end  

其中的方法都是类方法。在Init函数中我们完成了所有我们自定义界面的绘制(添加了四个UIButton和一个UILabel)。




5.

修改MyViewInit.m如下:

[cpp] view plain copy
  1. //  
  2. //  MyViewInit.m  
  3. //  Unity-iPhone  
  4. //  
  5. //  Created by tao hu on 9/15/12.  
  6. //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.  
  7. //  
  8.   
  9. #import "MyViewInit.h"  
  10.   
  11. @interface MyViewInit ()  
  12.   
  13. @end  
  14.   
  15. @implementation MyViewInit  
  16.   
  17.   
  18. //创建按钮  
  19. +(void)CreateButton:title rect:(CGRect)rect action:(SEL)action controller:(UIViewController *)controller  
  20. {  
  21.     UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];  
  22.   
  23.     //设置按钮范围      
  24.     btn.frame = rect;  
  25.   
  26.     //设置按钮显示内容      
  27.     [btn setTitle:title forState:UIControlStateNormal];  
  28.   
  29.     //设置按钮改变后绑定的响应方法      
  30.     [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];      
  31.       
  32.     //加入View中  
  33.     [controller.view addSubview:btn];  
  34. }  
  35.   
  36.   
  37. //创建标签  
  38. +(void)CreateTitle:(UIViewController *)controller  
  39. {  
  40.     //创建label视图      
  41.     UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];  
  42.     //设置显示内容      
  43.     label.text = @"旋转控制";      
  44.     //设置背景颜色      
  45.     label.backgroundColor = [UIColor blueColor];      
  46.     //设置文字颜色      
  47.     label.textColor = [UIColor whiteColor];      
  48.     //设置显示位置居中      
  49.     label.textAlignment = UITextAlignmentCenter;      
  50.     //设置字体大小      
  51.     label.font = [UIFont fontWithName:[[UIFont familyNames] objectAtIndex:10] size:20];   
  52.       
  53.     [controller.view addSubview:label];  
  54. }  
  55.   
  56.   
  57. //向左按钮    
  58. +(void)LeftButtonPressed  
  59. {    
  60.     UnitySendMessage("Cube""MoveLeft","");    
  61. }    
  62.   
  63. //向右按钮    
  64. +(void)RightButtonPressed  
  65. {    
  66.     UnitySendMessage("Cube""MoveRight","");    
  67. }    
  68. //向上按钮    
  69. +(void)UpButtonPressed  
  70. {    
  71.     UnitySendMessage("Cube""MoveUp","");    
  72. }    
  73.   
  74. //向下按钮    
  75. +(void)DownButtonPressed  
  76. {    
  77.     UnitySendMessage("Cube""MoveDown","");    
  78. }    
  79.   
  80.   
  81. +(void)Init:(UIViewController *)controller  
  82. {  
  83.     [self CreateTitle:controller];  
  84.       
  85.     [self CreateButton:@"左旋转" rect:CGRectMake(0,  50, 100, 40) action:@selector(LeftButtonPressed) controller:controller];  
  86.     [self CreateButton:@"右旋转" rect:CGRectMake(0, 100, 100, 40) action:@selector(RightButtonPressed) controller:controller];  
  87.     [self CreateButton:@"上旋转" rect:CGRectMake(0, 150, 100, 40) action:@selector(UpButtonPressed) controller:controller];  
  88.     [self CreateButton:@"下旋转" rect:CGRectMake(0, 200, 100, 40) action:@selector(DownButtonPressed) controller:controller];  
  89. }  
  90.   
  91.   
  92.   
  93. @end  


其中:

UnitySendMessage函数有三个参数:

第一个是Scene中的模型的名称,第二个是已经绑定在模型上的某个函数,第三个是char *类型的参数,用来将参数传递给这个函数。


我们可以用这个方法调用Unity3d中的任意一个模型上的任意一个函数。




6.

最后我们要做的是在程序启动时调用上面的Init函数。找到AppController.mm文件:

[cpp] view plain copy
  1. int OpenEAGL_UnityCallback(UIWindow** window, int* screenWidth, int* screenHeight,  int* openglesVersion)  

函数在Unity3d程序启动时会被调用,其中的EAGLView 就是Unity3d的背景的那个View。我们在这个函数中调用我们的Init函数。修改OpenEAGL_UnityCallback如下:

[cpp] view plain copy
  1. int OpenEAGL_UnityCallback(UIWindow** window, int* screenWidth, int* screenHeight,  int* openglesVersion)  
  2. {  
  3.     CGRect rect = [[UIScreen mainScreen] bounds];  
  4.   
  5.     // Create a full-screen window  
  6.     _window = [[UIWindow alloc] initWithFrame:rect];  
  7.       
  8.       
  9.     EAGLView* view = [[EAGLView alloc] initWithFrame:rect];  
  10.     UnityViewController *controller = [[UnityViewController alloc] init];  
  11.       
  12.       
  13.     sGLViewController = controller;  
  14.   
  15. #if defined(__IPHONE_3_0)  
  16.     if( _ios30orNewer )  
  17.         controller.wantsFullScreenLayout = TRUE;  
  18. #endif  
  19.   
  20.     controller.view = view;  
  21.     [_window addSubview:view];  
  22.       
  23.       
  24.     [MyViewInit init:controller];  
  25.   
  26.   
  27.     if( !UnityUseOSAutorotation() )  
  28.     {  
  29.         _autorotEnableHandling = true;  
  30.         [[NSNotificationCenter defaultCenter] postNotificationName: UIDeviceOrientationDidChangeNotification object: [UIDevice currentDevice]];  
  31.     }  
  32.   
  33. ......  


其实我们只加入了一句话:

[cpp] view plain copy
  1. [MyViewInit init:controller];  


并在该文件首部加入:

[cpp] view plain copy
  1. #import "MyViewInit.h"  




7.

好了,终于要在真机上运行了:

初始界面:





点击下旋转按钮:




旋转Cube:




我们发现在XCode的Console窗口中输出了Unity3d中的pirnt语句。因此,Unity3d中的print函数在真机上运行时是输出到XCode的Console中。


(第二部分)


上篇中我们介绍Unity3d与iOS交互的第一部分:iOS传消息到Unity3d中。今天我们介绍第二部分:在Unity3d界面中传递消息到iOS中。下面我们开始吧:

如下图所示,本章我们的目标是在Unity3D 界面中添加两个GUI按钮,并且在iPhone上点击这两个按钮后分别弹出两个IOS 高级界面的对话框。相信盆友们对GUI应该不会太陌生,在这里我在前调一下GUI就是Unity3D 提供的一套UI系统。图中的两个UI 按钮我就是用GUI做出来的。

 

Unity3D研究院之Unity3D回馈IOS高级界面消息(十) - 雨松MOMO程序研究院 - 1

 

Project栏目中创建一个c#脚本,命名为Main.cs ,之前没有使用过 C#写脚本,今天我用C#来写这个脚本,哇咔咔~~~ 如下图所示将脚本拖动在摄像机上,脚本中声明两个Texture 类型变量用来保存按钮绘制的图片资源。


Unity3D研究院之Unity3D回馈IOS高级界面消息(十) - 雨松MOMO程序研究院 - 2
Main.cs 代码 

 

这里详细说一下SDK这个类,这个类我们看作它是一个管理类,它不赋值在任意对象身上,只接受调用管理,点击两个按钮后将分别调用下面方法中的_ActivateButton0() 与 _ActivateButton1(),而这两个方法则是去调用xcode 我们自己实现的方法_pressButton0() 与 _pressButton1(), 前提上须下面代码中的注册,这样子导出项目的时候xcode会帮我们 生成注册信息,我们只须要实现这两个方法就可以了。


SDK.cs 代码


 

这样子Unity3D 部分已经完成,将Untiy3D项目导出成Xcode项目,我们用Xcode打开它。添加Unit3D中GUI按钮点击后的响应事件。创建一个类命名为MyView.h 、MyView.m,用它来接收Unity3D 回馈回来的消息,_PressButton0 与 _PressButton1 这两个方法在Unity3D中已经注册过,所以在这个类中我们须要对它进行Xcode中的实现。

MyView.m

OK大功告成,连上真机运行我们的项目,我们在iPhone中点击了Unity3D 中GUI这两个按钮后,通过消息的回馈顺利的弹出IOS高级界面 的对话框,哇咔咔~

 

Unity3D研究院之Unity3D回馈IOS高级界面消息(十) - 雨松MOMO程序研究院 - 3

 

最后欢迎各位盆友可以和MOMO一起讨论Unity3D游戏开发,冬天就要来啦大家注意添加衣服,注意身体健康噢。哇咔咔~~~ 附上Unity3D工程的下载地址,Xcode项目我就不上传了,须要的自己导出。不早了,大家晚安,哇咔咔~~



2017-11-29 14:12:03 Tonny_007 阅读数 774
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

iOS与Unity3d的交互实现

最近在公司写的项目是基于iOS与Unity3d的,之前也写了不少的iOS与Unity的项目,但是这次将两者结合开发还是第一次。项目的第一条功能需求就是:实现从iOS原生界面到Unity的跳转。

看似简单,但是却不知道怎么下手,修改Unity导出到iOS的封装好的代码是肯定的,但是至于改哪里,怎么改却是比较难。和一般的coding一样,一上来先是各种找解决方案和样例,不管是国内大神雨松momo的博客,还是墙外的社区都是搜刮了一番,运气挺好,在某岛国的博客中有人写了一种解决方案。链接戳这里: 
https://github.com/mythosMatheWG/unityIntoIOSSample

这里提供的解决方案并没有给出完整的解释,原博主也只是一步步教你在哪里改代码,虽然能运行,但是却不知所以然。而且,这套解决方案有Bug,后来才知道:如果没有处理好ViewController与Unity之间的关系,会导致跳转到Unity之后出现如下错误:

opengles-error-0x0502
  • 1

然后你的Unity界面内容就糊掉了==!

——继续找,在另外一篇帖子里面看到了比较完整的另外一种解决方案,链接戳这里: 
http://game.ceeger.com/forum/read.php?tid=20533

这篇博客的教程就是在这两种解决方案的基础上进行的。旨在提供一套”你跟着做了就能够实现”的较为完整的解决方案。当然,前提是我们假设你会Unity,iOS的一些基础知识


开发环境

  • xcode 7.2
  • Unity4.6.3 (这个无所谓,因为build出来的OC代码没有太大变化)

开发语言

  • OC

正餐

先让了解一下Unity build出来的iOS工程项目的整个框架以及运行流程 
Unity导出的工程项目结构图

Main.mm作为整个项目的入口主要做了如下的事情

const char* AppControllerClassName = "UnityAppController";


int main(int argc, char* argv[])
{
    NSAutoreleasePool* pool = [NSAutoreleasePool new];

    UnityInitTrampoline();
    if(!UnityParseCommandLine(argc, argv))
        return -1;

#if INIT_SCRIPTING_BACKEND
    InitializeScriptingBackend();
#endif

    RegisterMonoModules();
    NSLog(@"-> registered mono modules %p\n", &constsection);
    RegisterFeatures();

    // iOS terminates open sockets when an application enters background mode.
    // The next write to any of such socket causes SIGPIPE signal being raised,
    // even if the request has been done from scripting side. This disables the
    // signal and allows Mono to throw a proper C# exception.
    std::signal(SIGPIPE, SIG_IGN);

    UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);

    [pool release];
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 初始化各个模块
  • 将UnityAppController作为控制类来实现Unity在iOS上显示的功能,换句话说,就是在main之后紧接着就要执行这个类里面的函数

所以视线转移到UnityAppController.mm这里,可以看到这里的代码结构和OC的一般类的代码结构类似,除此之外还有一些C语言程序,作为相对底层中Unity与iOS交互的桥梁,不用管。我们需要关注的是: 
UnityAppController.mm中函数执行的顺序以及我们能够在哪里加上我们自己的代码实现”项目入口”的修改,从而做到整个程序一上来先显示我们自己的View,然后通过自定义事件再来跳转到Unity部分。 
所以整个项目看起来就像把Unity导出的工程剖开,将我们自定义的部分”塞”进去,从而实现iOS与Unity3d的交互。

操作步骤

1.修改项目入口

从运行项目看到的输出可以知道,UnityAppController.mm函数的执行顺序为:

void UnityInitTrampoline()
- (id)init
-(BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
void AppController_SendUnityViewControllerNotification(NSString* name)
- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
- (void)preStartUnity
- (void)applicationDidBecomeActive:(UIApplication*)application
- (UIWindow*)window                 { return _window; }
...
- (void)startUnity:(UIApplication*)application
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

执行了StartUnity,会让Unity的界面就会显示出来。 
如果要修改项目入口,让Unity界面显示之前先显示我们需要的界面,就需要

在StartUnity函数执行之前实现入口修改,当我们需要跳转到Unity部分的时候再调用StartUnity

通过继承我们可以利用子类来复写UnityAppController中的函数,从而实现入口修改。我这里的做法是,创建一个UnitySubAppDelegate类(因为其作用与一般iOS工程项目中的AppDelegate类似,所以这么叫),这个类是继承自UnityAppController,能够对其函数进行复写。在这里我对StartUnity函数复写:

- (void)startUnity:(UIApplication *)application {

    self.myDataManager = [MyDataManager sharedManager];
    //myDataManager是一个单例,存放一些全局变量,用来进行跳转判断
    if(!self.myDataManager.isInMyHomeView)
    {
        //程序启动时判断是否进入了自定义界面,如果没有则跳转到自定义界面
        viewController= [EnterUnityPartViewController new];
        viewController.appDelegate = self;//将当前类传过去,用于实现从自定义界面启动unity
        viewController.window = self.window;
        self.window.rootViewController = viewController;
        self.myDataManager.myWindow = self.window;//将当前window存放为全局变量,用于后续原生界面与unity的来回切换(因为跳到unity界面之后系统会释放window指针)
    }
    else{
        [super startUnity:application];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

代码中可以看到,实现修改程序入口的本质就是对window进行修改:

  • 将window指针传给自定义的VC
  • 将自定义的VC作为当前window的rootViewController

进行这样的操作,程序就会在启动后跳转到我们自定义的View上了。

2.从自定义界面启动Unity

我们已经知道,启动Unity的函数是

- (void)startUnity:(UIApplication *)application
  • 1

那么在我们自定义的VC中我们就能利用这个方法实现从自定义界面启动Unity:

 [self.appDelegate startUnity:UIApplication.sharedApplication];//利用UIApplication.sharedApplication获取当前application
  • 1

这里的appDelegate就是在步骤1中传过来的值,所以我们需要在当前VC的头文件中定义一个appDelegate:

@property (strong, nonatomic) UnitySubAppDelegate *appDelegate;
  • 1

3.从Unity界面返回自定义界面

返回自定义的方法有很多,我这里用的方法是在当前window的rootView上面加上一个button来实现跳转(这部分代码同样是加在自定义的VC中,我这里的实现思路是在startUnity函数调用之后就加上按钮)

    UIView *pauseUnityView = [[UIView alloc] initWithFrame:CGRectMake(10, 25, 40, 40)];
    UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 30, 30)];
    pauseUnityView.backgroundColor = [UIColor whiteColor];
    backBtn.backgroundColor = [UIColor redColor];
    [backBtn addTarget:self action:@selector(doExitSelector) forControlEvents:UIControlEventTouchDown];
    [pauseUnityView addSubview:backBtn];
    [self.window.rootViewController.view addSubview:pauseUnityView];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

跳转实现函数为

- (void)doExitSelector{
    UnityPause(true);//跳走之前需要将unity停掉

    MyDataManager *myDataManager = [MyDataManager sharedManager];
    MyDataManager.unityViewController = self.window.rootViewController; //跳走之前需要将当前Unity所在的界面存放在单例中的全局变量内,以便后面再次跳转回Unity能够获取到界面。如果不保存,则根据ARC机制Unity跳转回来之后地址会自动释放,无法获取到界面

    [[[UnityGetMainWindow() rootViewController] view] setHidden:YES];

//    EnterUnityPartViewController *enterVC = [[EnterUnityPartViewController alloc]init];

    self.window.rootViewController = self;//由于当前的跳转函数是写在EnterUnityPartViewController里的,所以当unity再次跳转回来就直接将rootViewController赋值self即可。如果你想跳到其它界面,可以仿照上面注释的语句来实现界面跳转

    [UnityGetMainWindow() makeKeyAndVisible];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

之前我在找的第二个方案中提到的unity跳回自定义View方法是在Unity导出来的UnityAppController+ViewHandling.mm修改的。但是这样会挺麻烦,每次都要在项目导出后修改这部分代码。

4.从自定义界面跳转Unity

和步骤2不同,在Unity跳转回来后,Unity没有关闭,只是呈现挂起状态。所以Unity界面仍然存在,这也是我们为何在步骤3中需要把Unity界面保存在单例中。这里我们也只需要再进行一次界面跳转就能把Unity呈现出来:

if(self.myDataManger.isRestartInUnity)
        {
            if(!self.window)
            {
            //判断当前window是否为空,这个window是在subAppDelegate中赋值过来的,有可能在界面跳转过程中UnityAppController的window指针被置为空
                self.window = self.myDataManger.myWindow;
            }
            self.window.rootViewController = self.myDataManger.unityViewController;
            [self.window bringSubviewToFront: self.myDataManger.unityViewController.view];//把UnityView放到最前面
            [[[UnityGetMainWindow() rootViewController] view]setHidden:NO];
            [UnityGetMainWindow() makeKeyAndVisible];
            UnityPause(false);//取消暂停
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

至此,iOS与Unity3d的交互就在这四个步骤中实现。说到底并不难,主要搞懂了几个界面的关系以及iOS的Window,rootView的层级结构就行。 
项目文件

有任何问题及不足请指出

2018-08-24 16:19:08 u014084081 阅读数 938
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

在原生iOS集成Unity3D应用

在原生iOS集成Unity3D,可参考:

视频教程可参考:Integrating Unity3D with native iOS application,貌似比较老了,不过还是很有参考价值

记录下集成过程中遇到的问题:

1.对照Unity导出的iOS项目工程,很多设置可以直接拷贝过来,不用一个一个输入

2.首先要明白$(SRCROOT)的含义,可参考iOS开发之Xcode 相对路径与绝对路径

$(SRCROOT)宏和$(PROJECT_DIR)宏都指xxx.xcodeproj所在的父目录

在设置Header Search PathsLibrary Search Paths时,可能需要这个宏

3.Other C FlagsOther C++ Flags都要设置

-DINIT_SCRIPTING_BACKEND=1
-fno-strict-overflow
-DRUNTIME_IL2CPP=1

我当时是只设置了Other C Flags,未设置Other C++ Flags,导致提示cannot use 'try' with exceptions disabled

4.可能会提示__weak typeof(self) wSelf这种类型的错误,参考typeof 编译错误

__weak typeof(self) wSelf = self报错:- A parameter list without types is only allowed in a function definition. A corresponding warning tells me that __weak only applies to Objective-C object or block pointer types; type here is ‘int’

在教程中我们是将C Language Dialect设置为C99 [-std=c99],将其改成GNU99即可

5.提示

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x146746d0>) doesn't contain a view controller with identifier 'unitySplashStoryboard''

按教程中的说明修改:

解决办法如下:在SplashScreen.mm文件修改下面的方法
void ShowSplashScreen(UIWindow* window)
{
//    bool hasStoryboard = [[NSBundle mainBundle] pathForResource: @"LaunchScreen" ofType: @"storyboardc"] != nullptr;
//
//    if (hasStoryboard)
//    {
//        UIStoryboard *storyboard = [UIStoryboard storyboardWithName: @"LaunchScreen" bundle: [NSBundle mainBundle]];
//        _controller = [storyboard instantiateViewControllerWithIdentifier: @"unitySplashStoryboard"];
//    }
//    else
        _controller = [[SplashScreenController alloc] init];

    [_controller create: window];
    [window makeKeyAndVisible];
}

6.如下的几个方法一定要实现,否则unity会不显示

- (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 invalidate graphics rendering callbacks. 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 active 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];
}

7.导入Unity后,原来的动画被disable掉了 or 加载的HUD消失了,可参考解决整合原生xcode工程和unity3D发布的iOS工程导航栏推出视图控制器失去动画效果的坑


在集成Unity应用后,遇到了一些问题,记录如下:

1.无网络(关闭wifi和移动网络)时crash

按上面提到的教程集成Unity,在app启动时,初始化unity,暂时先隐藏unity,在需要的时候,再显示unity。但是如果,启动的时候,关闭掉wifi和移动网络,app一启动有很大的概率crash

使用umeng捕获的异常如下:

Application received signal SIGBUS
(null)
((
	0   CoreFoundation                      0x000000019081d1d0 <redacted> + 148
	1   libobjc.A.dylib                     0x000000018f25455c objc_exception_throw + 56
	2   CoreFoundation                      0x000000019081d100 <redacted> + 0
	3   CureFunNew!UmengSignalHandler
	4   libsystem_platform.dylib            0x000000018f8ad338 _sigtramp + 36
	5   CureFunNew!Job_ExecuteUnityWebRequest [dynamic_array.h : 473]
	6   CureFunNew!Exec [JobQueue.cpp : 386]
	7   CureFunNew!Steal [JobQueue.cpp : 613]
	8   CureFunNew!ExecuteJobFromQueue [JobQueue.cpp : 770]
	9   CureFunNew!ProcessJobs [JobQueue.cpp : 823]
	10  CureFunNew!WorkLoop [JobQueue.cpp : 909]
	11  CureFunNew!RunThreadWrapper [thread.cpp : 36]
	12  libsystem_pthread.dylib             0x000000018f8b1850 <redacted> + 240
	13  libsystem_pthread.dylib             0x000000018f8b1760 <redacted> + 0
	14  libsystem_pthread.dylib             0x000000018f8aed94 thread_start + 4
)

使用真机来调试,也捕获到如上的异常:

unity异常

集成非模拟器的unity包后,貌似不能在模拟器上运行调试了,而且使用真机调试unity的时候,也会直接卡住,如何解决呢?
如下,Metal API Validation 设置为 disabled

edit schema

可参考:

至于如何解决启动时的崩溃,可以尝试,不要在app启动的时候,加载unity

2.如何展示unity的问题

在展示untiy的时候,通常会要处理旋转问题,一般的app只支持portrait,而unity通常则需要横屏

如果unity中不需要弹出键盘,即不需要处理键盘的方向的话,可直接把view旋转

如果需要处理键盘的方向,可重写AppDelegateapplication:supportedInterfaceOrientationsForWindow:的方法

可参考:

另外在这篇文章:将Unity3D 添加到IOS具体页面 以及横屏显示中,使用的是模态弹出unity,这样做的优点是,可以直接控制旋转,非常有参考的价值

Unity3d与iOS的交互

阅读数 2557