Unity引擎与原生安卓和IOS开发交互的实现

打印 上一主题 下一主题

主题 940|帖子 940|积分 2835

Unity引擎与原生安卓和iOS开发的交互是游戏开发中常见的需求,尤其是在须要调用平台特性(如付出、广告、相机、传感器等)时。这种交互通常通过Unity与原生代码的桥接来实现,包括在Unity中调用原生安卓/Objective-C代码,或者让原生应用调用Unity代码。以下是具体的实现方法与示例。

1. Unity与原生交互的核心原理

1.1 Unity调用原生代码

Unity可以通过插件机制调用安卓的Java或iOS的Objective-C/Swift代码。核心机制为:


  • 安卓:通过AndroidJavaObject和AndroidJavaClass调用原生Java方法。
  • iOS:通过[DllImport("__Internal")]调用Objective-C或Swift的C接口。

1.2 原生代码调用Unity

安卓和iOS可以通过Unity提供的接口与Unity的C#脚本交互:


  • 安卓:使用UnityPlayer对象的静态方法UnitySendMessage。
  • iOS:通过UnitySendMessage函数与Unity通讯。

2. Unity调用安卓代码

2.1 实现步骤


  • 创建安卓原生插件
  • 在Unity中调用安卓插件
  • 处理数据的通报与回调

2.2 示例:调用安卓的Toast提示

(1) 创建安卓原生插件


  • 在Android Studio中新建一个安卓模块,添加一个包罗Toast逻辑的类。
  • 编译此模块为.aar文件。
以下是一个简单的安卓插件代码:
  1. package com.example.unityplugin;
  2. import android.content.Context;
  3. import android.widget.Toast;
  4. public class AndroidPlugin {
  5.     private static Context unityContext;
  6.     // 初始化Unity的Context
  7.     public static void initialize(Context context) {
  8.         unityContext = context;
  9.     }
  10.     // 显示Toast消息
  11.     public static void showToast(final String message) {
  12.         if (unityContext != null) {
  13.             Toast.makeText(unityContext, message, Toast.LENGTH_LONG).show();
  14.         }
  15.     }
  16. }
复制代码

  • 添加UnityPlayerActivity的Context初始化代码:
    1. // 在UnityPlayerActivity的onCreate方法中调用
    2. AndroidPlugin.initialize(this);
    复制代码
  • 编译生成.aar插件,并将其放入Unity项目的Assets/Plugins/Android/文件夹。

(2) Unity中调用安卓代码

在Unity项目中,使用AndroidJavaObject调用Java代码:
  1. using UnityEngine;
  2. public class AndroidToast : MonoBehaviour
  3. {
  4.     public void ShowToast(string message)
  5.     {
  6.         if (Application.platform == RuntimePlatform.Android)
  7.         {
  8.             // 调用安卓插件中的方法
  9.             AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  10.             AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  11.             AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.unityplugin.AndroidPlugin");
  12.             // 调用插件的showToast方法
  13.             pluginClass.CallStatic("showToast", message);
  14.         }
  15.     }
  16. }
复制代码
(3) 测试结果


  • 在Unity中创建一个UI按钮。
  • 将上述AndroidToast脚本挂载到按钮的OnClick事故。
  • 在安卓装备上运行,点击按钮会显示Toast消息。

3. Unity调用iOS代码

3.1 实现步骤


  • 在Xcode中创建Objective-C或Swift代码
  • 通过DllImport桥接Unity与原生代码
  • 处理数据通报与回调

3.2 示例:调用iOS的体系弹框

(1) 创建iOS原生代码

在Unity项目的Plugins/iOS目录下创建一个Objective-C文件(如NativeIOSPlugin.m),实现弹框逻辑。
  1. #import <Foundation/Foundation.h>
  2. #import <UIKit/UIKit.h>
  3. // 显示iOS原生弹框
  4. void ShowIOSAlert(const char* title, const char* message) {
  5.     NSString* alertTitle = [NSString stringWithUTF8String:title];
  6.     NSString* alertMessage = [NSString stringWithUTF8String:message];
  7.     dispatch_async(dispatch_get_main_queue(), ^{
  8.         UIAlertController* alert = [UIAlertController alertControllerWithTitle:alertTitle
  9.                                                                        message:alertMessage
  10.                                                                 preferredStyle:UIAlertControllerStyleAlert];
  11.         UIAlertAction* okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
  12.         [alert addAction:okAction];
  13.         UIViewController* rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  14.         [rootViewController presentViewController:alert animated:YES completion:nil];
  15.     });
  16. }
复制代码

(2) Unity中调用iOS代码

在Unity脚本中,通过[DllImport("__Internal")]桥接到Objective-C的C函数。
  1. using System.Runtime.InteropServices;
  2. using UnityEngine;
  3. public class IOSAlert : MonoBehaviour
  4. {
  5.     // 引用iOS原生方法
  6.     [DllImport("__Internal")]
  7.     private static extern void ShowIOSAlert(string title, string message);
  8.     public void ShowAlert(string title, string message)
  9.     {
  10.         if (Application.platform == RuntimePlatform.IPhonePlayer)
  11.         {
  12.             ShowIOSAlert(title, message);
  13.         }
  14.     }
  15. }
复制代码

(3) 测试结果


  • 将IOSAlert脚本挂载到一个按钮。
  • 在iOS装备上运行,点击按钮会弹出体系的原生弹框。

4. 原生代码调用Unity

Unity提供了UnitySendMessage方法,允许原生代码调用Unity中的C#方法。

4.1 安卓调用Unity

(1) 原生代码调用Unity

在安卓Java代码中,使用UnityPlayer.UnitySendMessage发送消息到Unity。
  1. package com.example.unityplugin;
  2. public class AndroidPlugin {
  3.     public static void CallUnityFunction(String gameObjectName, String methodName, String message) {
  4.         // 调用Unity的C#方法
  5.         com.unity3d.player.UnityPlayer.UnitySendMessage(gameObjectName, methodName, message);
  6.     }
  7. }
复制代码
(2) Unity中接收消息

在Unity中,创建一个接收消息的C#脚本:
  1. using UnityEngine;
  2. public class UnityReceiver : MonoBehaviour
  3. {
  4.     // 被原生代码调用的C#方法
  5.     public void OnReceiveMessage(string message)
  6.     {
  7.         Debug.Log("Received message from Android: " + message);
  8.     }
  9. }
复制代码
将该脚本挂载到一个GameObject,确保该GameObject的名称与UnitySendMessage中一致。

(3) 测试结果


  • 在安卓代码中调用:
    1. AndroidPlugin.CallUnityFunction("GameObjectName", "OnReceiveMessage", "Hello from Android!");
    复制代码
  • Unity中会打印日志:Received message from Android: Hello from Android!

4.2 iOS调用Unity

(1) 原生代码调用Unity

在iOS代码中,使用UnitySendMessage方法发送消息到Unity。
  1. #import "UnityInterface.h"
  2. void CallUnityFunction(const char* gameObjectName, const char* methodName, const char* message) {
  3.     UnitySendMessage(gameObjectName, methodName, message);
  4. }
复制代码
(2) Unity中接收消息

与安卓的UnityReceiver脚本相同,Unity会通过UnitySendMessage调用指定的C#方法。

(3) 测试结果


  • 在iOS代码中调用:
    1. CallUnityFunction("GameObjectName", "OnReceiveMessage", "Hello from iOS!");
    复制代码
  • Unity中会打印日志:Received message from iOS: Hello from iOS!

5. 数据通报与回调

数据通报和回调是Unity与原生交互的重要部分,以下是常见的数据通报和回调方式。

5.1 Json数据通报

通过字符串通报复杂数据,推荐使用Json格式。
Unity发送Json到原生代码

  1. string jsonData = JsonUtility.ToJson(new { name = "Unity", age = 5 });
  2. pluginClass.CallStatic("ReceiveJsonData", jsonData);
复制代码
原生代码剖析Json

  1. import org.json.JSONObject;
  2. public static void ReceiveJsonData(String jsonData) {
  3.     try {
  4.         JSONObject json = new JSONObject(jsonData);
  5.         String name = json.getString("name");
  6.         int age = json.getInt("age");
  7.     } catch (Exception e) {
  8.         e.printStackTrace();
  9.     }
  10. }
复制代码

5.2 回调机制

在Unity与原生交互中,回调用于将处理结果返回给调用方。
Unity中定义回调方法

  1. public void OnNativeCallback(string result)
  2. {
  3.     Debug.Log("Received callback from native: " + result);
  4. }
复制代码
原生代码调用回调

  1. UnityPlayer.UnitySendMessage("GameObjectName", "OnNativeCallback", "Callback Result");
复制代码

6. 总结与建议


  • 插件架构

    • 安卓使用.aar插件,iOS使用Objective-C/Swift代码,分别放入Assets/Plugins/Android和Assets/Plugins/iOS目录。

  • 数据通报

    • 推荐使用Json格式通报复杂数据,方便跨平台剖析。

  • 双向交互

    • 使用UnitySendMessage实现原生代码调用Unity,使用AndroidJavaObject或DllImport实现Unity调用原生代码。

  • 调试与测试

    • 使用Unity日志和原平生台的调试工具(如Logcat、Xcode控制台)定位题目。

通过上述方法,可以在Unity项目中高效实现与原生安卓和iOS代码的交互,充分利用平台特性,为游戏提供更丰富的功能支持。


7. 进阶:Unity与原生安卓/iOS交互的高级应用

在实现基础的Unity与原生安卓/iOS交互后,可以进一步扩展到更复杂的场景,如调用体系特性、集成第三方SDK、实现跨平台特性支持、以及优化性能和兼容性。以下是进阶内容的具体讲解。

7.1 调用体系特性

Unity项目中,偶然须要直接使用安卓或iOS体系的功能,例如相机、传感器、定位服务等。以下是一些常见的体系特性实现。

1. 调用相机并返回照片

安卓端实现


  • 在Java中实现调用相机的逻辑
    1. package com.example.unityplugin;
    2. import android.app.Activity;
    3. import android.content.Intent;
    4. import android.net.Uri;
    5. import android.provider.MediaStore;
    6. public class CameraPlugin {
    7.     private static final int REQUEST_IMAGE_CAPTURE = 1;
    8.     private static Uri photoUri;
    9.     public static void openCamera(Activity activity, String imagePath) {
    10.         Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    11.         photoUri = Uri.parse(imagePath);
    12.         takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
    13.         activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    14.     }
    15.     // 获取拍照完成后的图片路径
    16.     public static String getPhotoPath() {
    17.         return photoUri != null ? photoUri.toString() : "";
    18.     }
    19. }
    复制代码
  • 在Unity中调用CameraPlugin
    1. using UnityEngine;
    2. public class CameraController : MonoBehaviour
    3. {
    4.     private const string pluginClassName = "com.example.unityplugin.CameraPlugin";
    5.     public void OpenCamera(string imagePath)
    6.     {
    7.         if (Application.platform == RuntimePlatform.Android)
    8.         {
    9.             using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    10.             {
    11.                 AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    12.                 using (AndroidJavaClass pluginClass = new AndroidJavaClass(pluginClassName))
    13.                 {
    14.                     pluginClass.CallStatic("openCamera", activity, imagePath);
    15.                 }
    16.             }
    17.         }
    18.     }
    19.     public string GetPhotoPath()
    20.     {
    21.         if (Application.platform == RuntimePlatform.Android)
    22.         {
    23.             using (AndroidJavaClass pluginClass = new AndroidJavaClass(pluginClassName))
    24.             {
    25.                 return pluginClass.CallStatic<string>("getPhotoPath");
    26.             }
    27.         }
    28.         return string.Empty;
    29.     }
    30. }
    复制代码
  • 测试结果

    • 调用OpenCamera方法打开相机。
    • 拍照完成后调用GetPhotoPath方法获取照片路径。


iOS端实现


  • 在Objective-C中实现相机调用逻辑
    1. #import <UIKit/UIKit.h>
    2. void OpenCamera(const char* callbackObject, const char* callbackMethod) {
    3.     dispatch_async(dispatch_get_main_queue(), ^{
    4.         UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    5.         picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    6.         picker.delegate = (id<UINavigationControllerDelegate, UIImagePickerControllerDelegate>)[UIApplication sharedApplication].delegate;
    7.         [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:picker animated:YES completion:nil];
    8.     });
    9. }
    复制代码
  • 在Unity中调用相机功能
    1. using System.Runtime.InteropServices;
    2. using UnityEngine;
    3. public class IOSCameraController : MonoBehaviour
    4. {
    5.     [DllImport("__Internal")]
    6.     private static extern void OpenCamera(string callbackObject, string callbackMethod);
    7.     public void OpenIOSCamera()
    8.     {
    9.         if (Application.platform == RuntimePlatform.IPhonePlayer)
    10.         {
    11.             OpenCamera(gameObject.name, "OnPhotoCaptured");
    12.         }
    13.     }
    14.     private void OnPhotoCaptured(string photoPath)
    15.     {
    16.         Debug.Log("Photo saved at: " + photoPath);
    17.     }
    18. }
    复制代码
  • 测试结果

    • 调用OpenIOSCamera方法打开相机。
    • 实现OnPhotoCaptured回调,处理照片路径。


2. 调用定位服务

安卓端实现

在Java中实现定位服务:
  1. package com.example.unityplugin;
  2. import android.app.Activity;
  3. import android.location.Location;
  4. import android.location.LocationManager;
  5. public class LocationPlugin {
  6.     public static String getLocation(Activity activity) {
  7.         LocationManager locationManager = (LocationManager) activity.getSystemService(Activity.LOCATION_SERVICE);
  8.         Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
  9.         if (location != null) {
  10.             return location.getLatitude() + "," + location.getLongitude();
  11.         } else {
  12.             return "No Location Available";
  13.         }
  14.     }
  15. }
复制代码
在Unity中调用:
  1. using UnityEngine;
  2. public class LocationController : MonoBehaviour
  3. {
  4.     private const string pluginClassName = "com.example.unityplugin.LocationPlugin";
  5.     public string GetLocation()
  6.     {
  7.         if (Application.platform == RuntimePlatform.Android)
  8.         {
  9.             using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
  10.             {
  11.                 AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  12.                 using (AndroidJavaClass pluginClass = new AndroidJavaClass(pluginClassName))
  13.                 {
  14.                     return pluginClass.CallStatic<string>("getLocation", activity);
  15.                 }
  16.             }
  17.         }
  18.         return string.Empty;
  19.     }
  20. }
复制代码
iOS端实现

使用CoreLocation框架获取定位信息。

  • 在Objective-C中实现定位逻辑:
    1. #import <CoreLocation/CoreLocation.h>
    2. NSString* GetLocation() {
    3.     CLLocationManager *locationManager = [[CLLocationManager alloc] init];
    4.     CLLocation *location = locationManager.location;
    5.     if (location) {
    6.         return [NSString stringWithFormat:@"%f,%f", location.coordinate.latitude, location.coordinate.longitude];
    7.     } else {
    8.         return @"No Location Available";
    9.     }
    10. }
    复制代码
  • 在Unity中调用:
    1. [DllImport("__Internal")]
    2. private static extern string GetLocation();
    3. public string FetchLocation()
    4. {
    5.     if (Application.platform == RuntimePlatform.IPhonePlayer)
    6.     {
    7.         return GetLocation();
    8.     }
    9.     return "Location Not Available";
    10. }
    复制代码

7.2 集成第三方SDK

在Unity中,通常须要集成第三方的安卓/iOS SDK(如付出SDK、广告SDK、推送服务)。以下是通用的集成步骤。

1. 集成安卓SDK

(1) 将SDK导入Unity



  • 将SDK提供的.aar或.jar文件放入Assets/Plugins/Android目录。
  • 如果SDK须要权限或设置文件,编辑AndroidManifest.xml。
(2) 调用SDK方法

通过AndroidJavaObject或AndroidJavaClass调用SDK中的方法。例如,调用广告SDK的初始化方法:
  1. using UnityEngine;
  2. public class AdManager : MonoBehaviour
  3. {
  4.     public void InitializeAdSDK()
  5.     {
  6.         if (Application.platform == RuntimePlatform.Android)
  7.         {
  8.             using (AndroidJavaClass adSdkClass = new AndroidJavaClass("com.example.adsdk.AdSDK"))
  9.             {
  10.                 adSdkClass.CallStatic("initialize", "YOUR_APP_ID");
  11.             }
  12.         }
  13.     }
  14. }
复制代码

2. 集成iOS SDK

(1) 将SDK导入Unity



  • 将iOS SDK的静态库文件(.a或.framework)放入Assets/Plugins/iOS目录。
  • 编辑Info.plist文件,添加所需的权限声明。
(2) 调用SDK方法

通过[DllImport("__Internal")]调用SDK的方法。例如,调用付出SDK的付出接口:
  1. [DllImport("__Internal")]
  2. private static extern void StartPayment(string productId);
  3. public void PurchaseProduct(string productId)
  4. {
  5.     if (Application.platform == RuntimePlatform.IPhonePlayer)
  6.     {
  7.         StartPayment(productId);
  8.     }
  9. }
复制代码

7.3 优化与兼容性

1. 优化性能



  • 淘汰跨语言调用:将频繁调用的逻辑放在原生层处理,淘汰Unity与原生之间的交互。
  • 异步处理:对于耗时操纵(如相机、定位),使用异步回调避免阻塞主线程。

2. 确保兼容性



  • 安卓

    • 检查不同装备和安卓版本的兼容性。
    • 在AndroidManifest.xml中声明须要的权限。

  • iOS

    • 确保支持不同的iOS版本。
    • 在Info.plist中声明须要的键值(如相机、定位权限)。


8. 总结与展望

Unity与原生安卓/iOS交互为游戏开发提供了强大的扩展能力,可以或许调用平台特性并集成第三方服务,为玩家带来更丰富的体验。以下是关键点总结:

  • 基础交互

    • 使用AndroidJavaObject和DllImport实现Unity与原生的双向通讯。
    • 在原生代码中使用UnitySendMessage调用Unity方法。

  • 体系特性

    • 调用相机、定位等体系功能,扩展游戏能力。
    • 动态加载资源,优化内存和性能。

  • SDK集成

    • 在Unity中集成广告、付出、分析等第三方SDK。
    • 确保跨平台兼容性,优化用户体验。

  • 高级优化

    • 使用Json通报复杂数据,简化跨语言交互。
    • 异步回调处理耗时使命,避免主线程阻塞。

通过这些技术,开发者可以在Unity项目中充分利用安卓和iOS平台的特性,同时保持高效的开发流程和良好的用户体验。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连全瓷种植牙齿制作中心

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表