杰瑞科技汇

unity3d 调用 java

这个过程的核心是 Android Java Interface (JNI),Unity 提供了一套非常方便的 API 来简化这个交互过程,你不需要自己去写复杂的 JNI 代码。

unity3d 调用 java-图1
(图片来源网络,侵删)

下面我将为你详细讲解整个流程,从环境搭建到代码实现,并提供一个完整的示例。


核心概念

  1. Android Java Interface (JNI):这是 Java 和 C/C++(以及通过 C# 调用的 C/C++)之间进行通信的桥梁,Unity 在底层已经封装了大部分 JNI 的复杂性。
  2. AndroidJavaClassAndroidJavaObject:这是 Unity 提供的两个核心类,用于与 Java 代码交互。
    • AndroidJavaClass:用于引用一个静态的 Java 类java.lang.Stringandroid.os.Build)。
    • AndroidJavaObject:用于引用一个类的实例(对象)new android.content.Intent())。
  3. using UnityEngine;:确保你的 C# 脚本顶部有这行引用,这样才能使用 Unity 的 AndroidJavaClassAndroidJavaObject

调用流程

整个过程可以概括为以下几个步骤:

  1. 在 Unity 中编写 C# 脚本:使用 AndroidJavaClassAndroidJavaObject 来定位并调用 Java 类/方法。
  2. 打包 Android APK:将 Unity 项目构建成 Android 应用。
  3. 在 Android Studio 中创建一个 UnityPlugin (AAR/JAR)
    • 编写你的 Java 代码。
    • 将 Java 代码打包成一个 Android 库(AAR 或 JAR 文件)。
  4. 在 Unity 中集成 Plugin
    • 将生成的 AAR/JAR 文件以及所需的资源(如 AndroidManifest.xml)放入 Unity 项目的 Assets/Plugins/Android 目录下。
  5. 在设备上测试:运行应用,验证 C# 调用 Java 的功能是否正常工作。

详细步骤与示例

假设我们的目标是:在 Unity 中点击一个按钮,调用一个自定义的 Java 方法,该方法会在 Android 的 Logcat 中打印一条自定义信息。

第 1 步:在 Unity 中创建 C# 脚本

这个脚本将作为调用 Java 代码的入口。

unity3d 调用 java-图2
(图片来源网络,侵删)
  1. 在 Unity 中创建一个新的 C# 脚本,命名为 CallJavaExample.cs
  2. 将其挂载到场景中的一个 GameObject 上(一个主摄像机或者一个空对象)。
  3. 编写以下代码:
using UnityEngine;
using UnityEngine.UI; // 如果需要用到 Button
public class CallJavaExample : MonoBehaviour
{
    // 在 Unity 编辑器中,将你的 Button 拖拽到这里
    public Button callJavaButton;
    void Start()
    {
        // 确保按钮存在并添加点击事件
        if (callJavaButton != null)
        {
            callJavaButton.onClick.AddListener(OnCallJavaButtonClicked);
        }
    }
    // 按钮点击时调用的方法
    public void OnCallJavaButtonClicked()
    {
        Debug.Log("C#: Button clicked, trying to call Java method...");
        // 检查当前平台是否为 Android
        if (Application.platform == RuntimePlatform.Android)
        {
            try
            {
                // --- 关键代码 ---
                // 1. 创建 Java 类的实例
                // "com.example.myunityplugin.UnityPlugin" 是我们稍后要创建的 Java 类的完整路径
                // 注意:这里的路径必须与 Java 代码中的 package 和 class name 完全一致
                using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
                {
                    // 2. 获取当前 Activity 的上下文
                    // AndroidJavaObject context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
                    // 另一种更通用的方式是直接使用 AndroidJavaClass
                    AndroidJavaObject pluginInstance = new AndroidJavaObject("com.example.myunityplugin.UnityPlugin");
                    // 3. 调用 Java 实例的公共方法
                    // "logToAndroidLog" 是我们 Java 类中的方法名
                    // "Hello from Unity C#!" 是要传递给 Java 方法的字符串参数
                    pluginInstance.Call("logToAndroidLog", "Hello from Unity C#!");
                    Debug.Log("C#: Successfully called Java method.");
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError("C#: Error calling Java: " + e.Message);
            }
        }
        else
        {
            Debug.Log("C#: Not running on Android. Skipping Java call.");
        }
    }
}

代码解释

  • new AndroidJavaClass("com.unity3d.player.UnityPlayer"):这是一个特殊的 Unity 内置类,它提供了与 Android Activity 交互的能力,我们用它来获取 Context
  • new AndroidJavaObject("com.example.myunityplugin.UnityPlugin"):这是我们即将创建的 Java 类。com.example.myunityplugin 是包名,UnityPlugin 是类名,请务必保持一致。
  • pluginInstance.Call("methodName", "param1", ...):这是调用 Java 实例方法的语法,第一个参数是方法名,后续是参数列表。

第 2 步:在 Android Studio 中创建 Java 插件

现在我们需要实现 com.example.myunityplugin.UnityPlugin 这个 Java 类。

  1. 新建 Android Studio 项目

    • 打开 Android Studio,选择 "File" -> "New" -> "New Project..."。
    • 选择 "Android Library" 模板,然后点击 "Next"。
    • 填写项目信息:
      • Name: MyUnityPlugin (或任何你喜欢的名字)
      • Package name: com.example.myunityplugin (必须与 C# 代码中的路径完全一致!)
      • Language: Java
      • Minimum SDK: API 21 或更高
    • 点击 "Finish"。
  2. 编写 Java 代码

    unity3d 调用 java-图3
    (图片来源网络,侵删)
    • java/com/example/myunityplugin 目录下,会自动生成一个 MainActivity.java删除它,因为我们不需要它。
    • 在同一个目录下,右键 -> "New" -> "Java Class",创建一个新类,命名为 UnityPlugin
    • 编写 UnityPlugin.java 的代码:
package com.example.myunityplugin;
import android.util.Log; // 导入 Log 类
public class UnityPlugin {
    // 定义一个用于打印日志的标签
    private static final String TAG = "MyUnityPlugin";
    // 这是一个公共的、非静态的方法,可以被 Unity C# 调用
    public void logToAndroidLog(String message) {
        // 使用 Android 的 Logcat 打印一条信息
        // Log.d(TAG, message) 表示 Debug 级别的日志
        Log.d(TAG, "Java: Received message from Unity -> " + message);
    }
}
  1. 构建 AAR 文件
    • 在 Android Studio 的顶部菜单栏,选择 "Build" -> "Build Bundle(s) / APK(s)" -> "Build Bundle(s)"。
    • 构建成功后,在项目目录的 app/build/outputs/aar/ 文件夹下会生成一个 release 文件夹,里面包含 app-release.aar 文件,这就是我们的插件库。

第 3 步:在 Unity 中集成插件

  1. 创建文件夹:在 Unity 项目的 Assets 目录下,创建一个名为 Plugins 的文件夹,然后在 Plugins 下再创建一个名为 Android 的文件夹,最终路径是 Assets/Plugins/Android
  2. 复制文件:将上一步生成的 app-release.aar 文件复制到 Assets/Plugins/Android 目录中。
  3. 检查并配置 Manifest(可选但推荐):
    • Unity 会自动使用 AAR 中自带的 AndroidManifest.xml,但如果你想添加自己的权限或配置,可以在 Unity 中创建一个 Assets/Plugins/Android/AndroidManifest.xml 文件,Unity 会合并这两个 Manifest 文件,你自己的配置会优先。

第 4 步:测试

  1. 在 Unity 中,创建一个 UI Button。
  2. 将之前创建的 CallJavaExample.cs 脚本挂载到场景中的某个 GameObject 上。
  3. 将这个 Button 拖拽到 CallJavaExample 脚本组件的 callJavaButton 字段上。
  4. 构建并运行:将项目构建设备或模拟器上。
  5. 查看 Logcat
    • 在 Android Studio 中,打开 "Logcat" 窗口(通常在底部)。
    • 在筛选器中选择你的应用包名(com.yourcompany.unityprojectname)。
    • 点击 Unity 中的 Button。
    • 你应该能在 Logcat 中看到类似下面这样的输出:
      D/MyUnityPlugin: Java: Received message from Unity -> Hello from Unity C#!

进阶主题

调用 Java 静态方法

Java 方法是 static 的,使用 AndroidJavaClass 会更方便。

Java 代码示例:

public class UnityPlugin {
    public static void staticLog(String message) {
        Log.d("StaticLog", "Java: Static method called with -> " + message);
    }
}

C# 调用代码:

// 使用 AndroidJavaClass 而不是 AndroidJavaObject
var javaClass = new AndroidJavaClass("com.example.myunityplugin.UnityPlugin");
// 调用静态方法,使用 CallStatic<>()
javaClass.CallStatic("staticLog", "This is a static call from C#!");

从 Java 返回值给 C

Java 方法可以返回任何基本数据类型或对象。

Java 代码示例:

public class UnityPlugin {
    public String getGreeting() {
        return "Greetings from Java!";
    }
}

C# 调用代码:

var pluginInstance = new AndroidJavaObject("com.example.myunityplugin.UnityPlugin");
// 调用方法并接收返回值,使用 <T> 指定返回类型
string greeting = pluginInstance.Call<string>("getGreeting");
Debug.Log("C#: Received greeting from Java: " + greeting);
// 输出: C#: Received greeting from Java: Greetings from Java!

传递复杂对象

你也可以在 C# 和 Java 之间传递自定义对象,但这需要更复杂的处理,通常需要实现序列化,对于初学者,建议先掌握基本数据类型和字符串的传递。


常见问题与注意事项

  • ClassNotFoundException:这是最常见的错误,几乎 100% 是因为 C# 代码中写的 Java 类路径(com.example.myunityplugin.UnityPlugin)与 Java 代码中的包名+类名不完全一致,请仔细检查大小写和点号。
  • NoClassDefFoundError:这通常意味着依赖项缺失,如果你在 Java 代码中引用了其他库(如 androidx.appcompat:appcompat),你需要将这些库的 AAR 文件也放到 Assets/Plugins/Android 目录中。
  • 平台检查:始终使用 if (Application.platform == RuntimePlatform.Android) 来包裹你的 Java 调用代码,这样在编辑器或 PC/Mac 上运行时就不会报错。
  • 线程问题:Unity 的主线程和 Android 的 UI 线程是同一个,如果你在 Java 代码中执行了耗时操作(如网络请求),它会阻塞 Unity 的渲染,导致卡顿,对于耗时操作,应该在 Java 中使用异步任务(如 AsyncTask, Thread, 或 Coroutine),并在完成后再通过 Unity 的 UnityPlayer.UnitySendMessage 方法回调通知 C#。

通过以上步骤,你就可以成功地在 Unity3D 中调用任何你需要的 Java 代码了,祝你开发顺利!

分享:
扫描分享到社交APP
上一篇
下一篇