{Unity} c#和iOS Objective-C交互
2016-01-15 17:54
483 查看
Unity
编写iOS native的Plugin, 接入一些sdk什么的,需要和OC进行交互。下面已我写的ios支付插件为例,总结一下。
1)c#调用OC代码
首先需要在c#中声明OC的函数:
这些函数前面要加入[DllImport("__Internal")],说明这是从dll导入的函数,并且来源于游戏本身的dll。函数必须声明为
private static extern void。
而函数的参数则可以是string,long等基本类型,我没试过其他类型,但是string, long, int已经够用了,如果是复杂的对象,可以转成一个json字符串,在OC那边再解析成对象。
以上的函数声明我放在一个PayNativeBridge.cs的c#文件中,并且又添加了几个封装的方法,方便客户C#代码调用,例如:
这是为了以后添加android等平台的代码,在客户代码中就可以无视平台的差异了。android的交互怎么处理以后再补充。
注意这个Init方法传人的参数,是一个GameObject对象的名称和该对象的一个函数名称,这个函数用于接受从OC代码传入的调用,因此叫callbackFunc。
2) OC实现import的函数
前面声明的这些DllImport的函数,需要在OC中实现,需要注意的是,函数的签名要符合C的调用规范,因此要加上extern "C"。例如:
这个函数的参数类型需要用c的类型,比如string要写成const char*。c#会自动识别到签名一致的函数,这点可比java的native代码调用方便了很多啊。这个函数里面我保存了传进来的
callbackGameObject和callbackFunc。这两个字符串是用来从OC回调C#的,下面就说一下。
3)OC回调Unity C#代码
当C#调用dllImport的OC代码后,OC代码进行一些处理,需要向C#返回处理的结果,这就需要使用Unity提供的发送回调事件的方法。从Unity导出的xcode工程中,已经包含了必要的头文件,其中UnityInterface.h中声明了一个方法:
void UnitySendMessage(const char* obj, const char* method, const char* msg);
在OC中使用这个方法可以向C#发送事件,回调C#的代码。参数obj就是上面保存的GameObject的名字,method即为回调函数名字,msg是发送的消息参数。需要说明的是,回调函数可以存在于GameObject所挂接的任意脚本组件上,但是函数签名必须符合public void Foo(string param)的格式。也就是说只能向C#脚本发送一个string参数。不过一个string已经够用了,通常的解决方案就是把需要发送的参数打包成一个json字符串。
下面是我封装一个方法,用于把一个整形的msgCode和一个data对象发送到Unity:
以下是从storeKit获取产品列表的方法,获取后发送给Unity:
编写iOS native的Plugin, 接入一些sdk什么的,需要和OC进行交互。下面已我写的ios支付插件为例,总结一下。
1)c#调用OC代码
首先需要在c#中声明OC的函数:
#if UNITY_IOS && !UNITY_EDITOR [DllImport ("__Internal")] private static extern void iosNativeInitPayCenter(string callbackGameObject, string callbackFunc); [DllImport ("__Internal")] private static extern void iosNativeRequestProducts(string storeName, string productIdListJson); [DllImport("__Internal")] private static extern void iosNativePay(string productId, long payId, string extendJsonData); #endif
这些函数前面要加入[DllImport("__Internal")],说明这是从dll导入的函数,并且来源于游戏本身的dll。函数必须声明为
private static extern void。
而函数的参数则可以是string,long等基本类型,我没试过其他类型,但是string, long, int已经够用了,如果是复杂的对象,可以转成一个json字符串,在OC那边再解析成对象。
以上的函数声明我放在一个PayNativeBridge.cs的c#文件中,并且又添加了几个封装的方法,方便客户C#代码调用,例如:
public void Init(string callbackGameObject, string callbackFunc) { #if UNITY_IOS && !UNITY_EDITOR iosNativeInitPayCenter(callbackGameObject, callbackFunc); #endif }
这是为了以后添加android等平台的代码,在客户代码中就可以无视平台的差异了。android的交互怎么处理以后再补充。
注意这个Init方法传人的参数,是一个GameObject对象的名称和该对象的一个函数名称,这个函数用于接受从OC代码传入的调用,因此叫callbackFunc。
2) OC实现import的函数
前面声明的这些DllImport的函数,需要在OC中实现,需要注意的是,函数的签名要符合C的调用规范,因此要加上extern "C"。例如:
static NSString *s_callbackGameObject; static NSString *s_callbackFunc; #if defined(_cplusplus) extern "C"{ #endif void iosNativeInitPayCenter(const char* callbackGameObject, const char* callbackFunc) { s_callbackGameObject = [NSString stringWithUTF8String: callbackGameObject]; s_callbackFunc = [NSString stringWithUTF8String: callbackFunc]; } #if defined(_cplusplus) } #endif
这个函数的参数类型需要用c的类型,比如string要写成const char*。c#会自动识别到签名一致的函数,这点可比java的native代码调用方便了很多啊。这个函数里面我保存了传进来的
callbackGameObject和callbackFunc。这两个字符串是用来从OC回调C#的,下面就说一下。
3)OC回调Unity C#代码
当C#调用dllImport的OC代码后,OC代码进行一些处理,需要向C#返回处理的结果,这就需要使用Unity提供的发送回调事件的方法。从Unity导出的xcode工程中,已经包含了必要的头文件,其中UnityInterface.h中声明了一个方法:
void UnitySendMessage(const char* obj, const char* method, const char* msg);
在OC中使用这个方法可以向C#发送事件,回调C#的代码。参数obj就是上面保存的GameObject的名字,method即为回调函数名字,msg是发送的消息参数。需要说明的是,回调函数可以存在于GameObject所挂接的任意脚本组件上,但是函数签名必须符合public void Foo(string param)的格式。也就是说只能向C#脚本发送一个string参数。不过一个string已经够用了,通常的解决方案就是把需要发送的参数打包成一个json字符串。
下面是我封装一个方法,用于把一个整形的msgCode和一个data对象发送到Unity:
-(void)callbackToUnity:(int) msgCode :(id)data { NSMutableDictionary *dictRoot = [NSMutableDictionary dictionaryWithCapacity:1]; NSNumber* msg = [NSNumber numberWithInt:msgCode]; [dictRoot setObject:msg forKey:@"msg"]; if(data!=nil){ [dictRoot setObject:data forKey:@"data"]; } NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictRoot options:kNilOptions error:&error]; NSString *jsonStr =[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; UnitySendMessage([s_callbackGameObject UTF8String], [s_callbackFunc UTF8String], [jsonStr UTF8String]); }
以下是从storeKit获取产品列表的方法,获取后发送给Unity:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSLog(@"AppleIAPDelegate: Received products request respose"); if ([response.invalidProductIdentifiers count]) { NSLog(@"Got invalid ones: %@", response.invalidProductIdentifiers); } NSArray* products = response.products; NSUInteger productCount = [products count]; NSLog(@"Procut Count:%lu", (unsigned long)productCount); NSMutableDictionary *outputProdcuts = [NSMutableDictionary dictionaryWithCapacity:productCount]; NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; for(int i=0; i<productCount; i++) { SKProduct *product = (SKProduct*)[products objectAtIndex:i]; [numberFormatter setFormatterBehavior:NSNumberFormatterBehaviorDefault]; [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; [numberFormatter setLocale:product.priceLocale]; NSString *formattedString = [numberFormatter stringFromNumber:product.price]; [outputProdcuts setObject:formattedString forKey:[product productIdentifier]]; //save products [mProducts setObject:product forKey:[product productIdentifier]]; } //callback to unity [self callbackToUnity:STORE_GET_PRODUCTS_SUCCESS :outputProdcuts]; if (request == mCurrentProductRequest) { mCurrentProductRequest = nil; } else { NSLog(@"AppleIAPDelegate: Warning: mCurrentProductRequest not responsed first!"); } }
相关文章推荐
- Unity+NGUI性能优化方法总结
- 回顾:Unity 游戏引擎发展历程
- Unity3D Texture to Sprite
- Unity3D游戏开发中制作场景
- Unity版本与虚拟现实头盔Deepoon大朋版本测试
- Unity版本与虚拟现实头盔Deepoon大朋版本测试
- Unity融合iOS所遇到的一些奇怪问题
- unity, imageEffect在android上不显示的问题
- Unity中的Mathf类
- unity3d 在android手机内读取assets目录内的资源
- Unity3d OnApplicationPause与OnApplicationFocus
- 关于unity里色彩空间与光照小记
- unity中的MonoBehaviour.OnMouseDown()
- 使用unity进行测试驱动开发的方法
- Unity3d之NGUI制作技能冷却
- unity移动平台阴影解决方案
- Unity3d 10000 Update() calls 性能优化
- unity3d打APK包时出现的内部构建错误(笔记)
- Unity3D——单词
- XML的使用,增删改查(Unity中的)