unity3d ios 交互
写这篇博文之前,我也为之忙活了半天,对于那些不熟悉oc的童鞋来说,非常有用,这里主要会讲到常用的通信机制。和一些关于IOS的代码讲解。
一下主要讲解使用unity3d调用IOS的界面浏览一张图片。
1.unity3d 与 IOS 的基本通信机制。
在C#脚本中,定义一个类,里面写入类似这样的
public static class PlatformNative{ [DllImport("__Internal")] private static extern void extern_lookImage(String tempfilepath); /// <summary> /// unity3d中使用 /// </summary> public static void LookImage(string tempfilepath) { extern_lookImage(tempfilepath); } }
引用 using System.Runtime.InteropServices;
unity3d 中直接调用LookImage 方法。
在XCode中编写相应的方法,这里我大概描述下我测试的设计模块。
定义一个辅助类 PlatformHelper.h,这个类主要用于处理OC系统接口的静态方法,因为很多系统接口多可以直接通过接口拿到。
class PlatformHelper { public: static void lookImage(const char* tempfilepath); static const char* getSystemVersion(int& len); };
实现PlatformHelper.mm:
void PlatformHelper::lookImage(const char* filepath){ NSString * _str = [NSString stringWithUTF8String:filepath]; NSLog(@"lookImage = %@", _str); //Create the RootViewController from a XIB file. ImageViewController *viewController=[[[ImageViewController alloc] init] autorelease]; viewController.imagePath = _str; //Add the RootViewController view to the main window. [[AlbumIOS shareInstance] push:viewController]; } const char* PlatformHelper::getSystemVersion(int& len) { NSString* version = Nil; version = [[UIDevice currentDevice] systemVersion]; len = version.length; return [version UTF8String]; }
注意,这种写法是C++和OC混合编写的。实现文件.mm为后缀。
然后,随便在一个类文件中定义如下C定义:
#if defined (__cplusplus) extern "C" { #endif void extern_lookImage(const char* str){ PlatformHelper::lookImage(str); } const char* extern_getSystemVersion(int& len){ return PlatformHelper::getSystemVersion(len); } #if defined (__cplusplus) } #endif
这一步就完成unity3d 和 IOS的通信接口了,extern_editFaceImage 这里和写在C#里面的名称一样,至于参数类型转化可以在网上查看,这里不讲解了。
我们这样写玩之后,在打包IOS项目时,unity3d会制动将C#中定义的[DllImport("__Internal")]函数注入到项目文件中,至于怎么关联的unity已经做好。注意,虽然写完了,但在模拟器上是不能直接调用的,要放到真机上。
好了,这里将重点,IOS上怎么弹出自己定义的view。
unity 游戏在IOS上有一个window.统一一起,这个window直接添加了一个unityviewcontroller,而不是nav( 全称 UINavigationControllerDelegate)。一般的IOS项目是将nav添加在window的子view中,而定义的viewcontroller添加在nav子view中。unity主要写在 unityAppcontroller内里可查看,这个模式是没有nav向导的,和状态栏的,就是个全屏界面。如果我们想在这个window下面添加自己定义的viewcontroller也是可以的,但是,没有nav,也就是说不能实现IOS viewcontroler的跳转,(注意,我没系统的学过OC,只是更具我的理解来说的)。unity 提供了一些函数,可以直接拿到它定义的那些类单列变量,如window,view,rootview等。
如果我们想打算自己弹出我们的view,就想第三方插件一样使用的话,我们应该这么做,尽量不去动unity3d自动生成的代码。
其实也很简单,重新创建一个window。这个window显示在unity window上面,然后把我们自定义的view添加到这个window上作为root 或 子view。要实现其他view的跳转的话解就可以给该window添加的子view 为一个实例化的nav,然后把自定义的view添加到 nav中去管理。
这里我把创建window当作一个公共的封装类作为单列模式,把要实现的不同功能的View独里开来,要打开不同功能的View只要先实例化该Viewcontroller,然后添加到单列window上去。
结构代码如下:
#import <UIKit/UIKit.h> @interface AlbumIOS : NSObject < UINavigationControllerDelegate> { UIViewController *viewCon; UINavigationController *nav; }; @property (strong, nonatomic)UIWindow *window; +(id) shareInstance; -(void) push:(UIViewController *) viewController; -(void) pop:(UIViewController *) viewController; @end
实现类:
#import "AlbumIOS.h" AlbumIOS *pInstance = nil; @implementation AlbumIOS @synthesize window = _window; +(id) shareInstance { if ( !pInstance ) { [[AlbumIOS alloc] init]; } return pInstance; } - (id)init { if(self = [super init]) { pInstance = self; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; nav = [[UINavigationController alloc] initWithRootViewController:nil]; nav.toolbarHidden = YES; nav.navigationBar.hidden = YES; [self.window setRootViewController:nav]; [self.window makeKeyAndVisible]; return self; } return nil; } -(void)dealloc { [nav release]; nav = nil; [self.window release]; self.window = nil; pInstance = nil; [super dealloc]; } -(void) push:(UIViewController*) view{ if(view==nil) return; viewCon = view; [viewCon setModalTransitionStyle:UIModalTransitionStyleCoverVertical]; [nav pushViewController:view animated:YES]; } -(void) pop:(UIViewController*) view{ if(view==nil) return; if(view==viewCon){ [self release]; } } @end
注意,这种写法更具需求情况不同而定,这里只是简单的写法,及同时只有一个功能模块打开才可以这么写(作为插件在游戏中一般一次性就弹出一个连窜的功能模块可以这么写)。
然和我们在单独做我们自定义的功能视图:这里就讲解下怎么浏览一张图片
定义:ImageViewController.h
#import <UIKit/UIKit.h> //查看图片 @interface ImageViewController : UIViewController { UIImage *image; } @property (copy, nonatomic)NSString *imagePath; @end
实现文件ImageViewController.mm:
#import "ImageViewController.h" #import "AlbumIOS.h" #pragma mark - ImageViewController @implementation ImageViewController @synthesize imagePath; - (void)viewDidLoad { [super viewDidLoad]; CGRect rect_screen = [[UIScreen mainScreen] bounds]; CGSize size_screen = rect_screen.size; //初始化显示截取后图片的ImageView UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size_screen.height, size_screen.width)]; imageView.image = [UIImage imageWithContentsOfFile:imagePath]; self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:imageView]; } -(void)dealloc { [super dealloc]; [imagePath release]; imagePath = nil; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [[AlbumIOS shareInstance] pop:self]; } - (BOOL)prefersStatusBarHidden { return YES; } @end
这样就可以在C#中调用lookImage方法通过传入制定文件目录的图片,在ios中用新的窗口打开。extern_getSystemVersion 方法调用一样的在C#中定义就可以了。
关于js ,boo 等和 C# 定义的区别请查看文档。道理差不多。
关于在IOS中统治unity 脚本C# 等 就更简单了,直接调用
UnitySendMessage("GameObject名称", "函数方法名", "字符串参数");
通知指定的gamobject中的脚本里面指定的函数。
好了,大家觉得有用就看看吧,有什么不懂的也可以留言。