iOS中,将C、C++、Objective-C代码,以及实现面向iOS编译的库作为本地插件使用。
以制作一个获取地理位置的本地插件为例。
创建名为 “LocationPlugin.mm” 的文件,放在Assets/Plugins/iOS文件夹下,代码如下:
// LocationPlugin.mm#import <Foundation/Foundation.h>#import <CoreLocation/CoreLocation.h>@interface LocationPlugin : NSObject<CLLocationManagerDelegate>// 采用CLLocationManagerDelegate协议{ CLLocationManager *locationManager; Nsstring *callbackTarget; bool isReverseGeoCoding; // 是否处于反地理编码处理}+ (LocationPlugin *)sharedInstance; @end// LocationPlugin类定义@implementation LocationPlugin// 单例static LocationPlugin *sharedInstance = nil;+ (ID)sharedInstance{ @synchronized(self) { if(sharedInstance == nil) { sharedInstance = [[self alloc] init]; } } return sharedInstance;}// 开始获取位置信息- (BOol)startUpdatingLocation:(Nsstring *)newCallbackTarget{ // 缓存回调 callbackTarget = newCallbackTarget; if(locationManager == nil) { locationManager = [[CLLocationManager alloc] init]; } // 确认位置信息服务是否有效且被许可 BOol isEnabledAndAuthorized = NO; if([CLLocationManager locationServicesEnabled]) { CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; if(status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizeDWhenInUse) { isEnabledAndAuthorized = YES; } } if(!isEnabledAndAuthorized) { // 位置信息服务无效且未被许可时,请求用户授权 [locationManager requestWhenInUseAuthorization]; return NO; } // 开始获取位置信息 locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBest; [locationManager startUpdatingLocation]; return YES;}// 停止获取位置信息- (voID)stopUpdatingLocation{ if(locationManager != nil) { [locationManager stopUpdatingLocation]; }}#pragma mark - CLLocationManagerDelegate协议的方法实现// 更新位置信息时调用- (voID)locationManager:(CLLocationManager *)manager dIDUpdateLocations:(NSArray *)locations{ if(isReverseGeoCoding) { return; } // 基于获取的位置信息进行反地理编码以获取地址 isReverseGeoCoding = YES; CLLocation *location = [locations lastObject]; CLGeocoder *geocoder = [[CLGeocoder alloc] init]; [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { isReverseGeoCoding = NO; // 从CLPlacemark对象的FormattedAddresslines中获取地址的字符串 Nsstring *addressstring = @""; if(placemarks.count >= 1) { CLPlacemark *placemark = [placemarks firstObject]; NSArray *addresslines = [placemark addressDictionary][@"FormattedAddresslines"]; addressstring = [addresslines componentsJoinedByString:@" "]; } // 创建作为参数传递的字符串 Nsstring *parameter = [Nsstring stringWithFormat:@"%f\t%f\t%f\t%f\t%@", location.coordinate.latitude, location.coordinate.longitude, location.speed, location.horizontalAccuracy, addressstring]; // 使用UnitySendMessage方法调用Unity的OnUpdateLocation方法 UnitySendMessage([callbackTarget cStringUsingEnCoding:NSUTF8StringEnCoding], "OnUpdateLocation", [parameter cStringUsingEnCoding:NSUTF8StringEnCoding]); }];}// 其他必须的方法- (voID)locationManager:(CLLocationManager *)manager dIDDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {}- (voID)locationManagerDIDPauseLocationUpdates:(CLLocationManager *)manager {}- (voID)locationManagerDIDResumeLocationUpdates:(CLLocationManager *)manager {}@end#pragma mark - 接口// 为回避C++命名粉碎,以C linkage进行声明extern "C" { // 用于调用开始获取位置信息方法的接口 BOol _startUpdatingLocation(const char *callbackTarget) { LocationPlugin *instance = [LocationPlugin sharedInstance]; @synchronized(instance) { return [instance startUpdatingLocation: [Nsstring stringWithUTF8String:callbackTarget]]; } } // 用于调用停止获取位置信息方法的接口 voID _stopUpdatingLocation() { LocationPlugin *instance = [LocationPlugin sharedInstance]; @synchronized(instance) { [instance stopUpdatingLocation]; } }}
注意选中LocationPlugin.mm脚本后,可以在Inspector面板中选择platforms for plugin,要选择iOS
接下来是从Unity方的脚本实现调用本地插件接口
创建名为 “LocationPluginInterface.cs” 的文件,代码如下
using UnityEngine;using System.Runtime.InteropServices;public class LocationPluginInterface{#if UNITY_IOS // 访问本地插件接口的声明 [Dllimport ("__Internal")] private static extern bool _startUpdatingLocation(string callbackTarget); [Dllimport ("__Internal")] private static extern voID _stopUpdatingLocation();#endif // 开始获取位置信息 public static bool StartUpdatingLocation(string callbackTarget) {#if !UNITY_EDITOR return _startUpdatingLocation(callbackTarget);#else return false;#endif } // 停止获取位置信息 public static voID StopUpdatingLocation() {#if !UNITY_EDITOR _stopUpdatingLocation();#endif }}
接下来是测试,测试脚本LocationExample.cs,代码如下(含有一些ui逻辑,根据实际需求进行设计),注意LocationExample.cs要挂到场景中的某个物体上,并且物体的名字要读一无二,因为本地插件回调是通过名字来找对应的物体的)
// LocationExample.csusing UnityEngine;using UnityEngine.UI;public class LocationExample : MonoBehavIoUr{ [SerializefIEld] private Text addressLabel; // 地址 [SerializefIEld] private Text latitudeLabel; // 维度 [SerializefIEld] private Text longitudeLabel; // 经度 [SerializefIEld] private Text speedLabel; // 移动速度 [SerializefIEld] private Text accuracyLabel; // 精度 // 是否正在获取位置信息 private bool IsUpdatingLocation { get; set; } voID Awake() { IsUpdatingLocation = false; UpdateUpdateLocationbutton(); } private voID UpdateUpdateLocationbutton() { Animator animator = GetComponent<Animator>(); if(animator != null) { animator.SetTrigger(IsUpdatingLocation? "Started": "Stopped"); } } // 按下开始/停止获取位置信息按钮 public voID OnPressUpdateLocationbutton() { IsUpdatingLocation = !IsUpdatingLocation; if(IsUpdatingLocation) { // 开始获取位置信息 if(!LocationPluginInterface.StartUpdatingLocation(this.name)) { IsUpdatingLocation = false; return; } } else { // 停止获取位置信息 LocationPluginInterface.StopUpdatingLocation(); } UpdateUpdateLocationbutton(); } // 位置信息更新时,从本地插件中回调过来 public voID OnUpdateLocation(string parameter) { // 取出参数 string[] components = parameter.Split(new char[] {'\t'}, 5); float latitude = float.Parse(components[0]); float longitude = float.Parse(components[1]); float speed = float.Parse(components[2]); float accuracy = float.Parse(components[3]); string address = components[4]; addressLabel.text = address; latitudeLabel.text = string.Format("{0:0}° {1:0}′", Mathf.Floor(latitude), (latitude - Mathf.Floor(latitude)) * 60); longitudeLabel.text = string.Format("{0:0}° {1:0}′", Mathf.Floor(longitude), (longitude - Mathf.Floor(longitude)) * 60); speedLabel.text = string.Format("{0:0.0} m/s", (speed >= 0.0f)? speed: 0.0f); accuracyLabel.text = string.Format("{0} m", accuracy); }}
总结 以上是内存溢出为你收集整理的Unity iOS本地插件的制作全部内容,希望文章能够帮你解决Unity iOS本地插件的制作所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)