Unity iOS本地插件的制作

Unity iOS本地插件的制作,第1张

概述iOS中,将C、C++、Objective-C代码,以及实现面向iOS编译的库作为本地插件使用。以制作一个获取地理位置的本地插件为例。创建名为 “LocationPlugin.mm” 的文件,放在Assets/Plugins/iOS文件夹下,代码如下:// LocationPlugin.mm#import <Foundation/Foundation.h>#import &l...

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本地插件的制作所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/998858.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存