☰
Unity调用Android原生入门:从零跑通第一个桥接方法
2026/10/18 13:37:10 网站建设 项目流程

简介:这份工具集面向希望打通 Unity 与原生安卓交互的开发者,尤其适合刚接触 JNI 与 Android 插件封装、需要快速上手的中级学习者。内容围绕 UnityActivity、UnityAppContext、PackageManager、RunOnUIThread 等基础方法展开,并覆盖 Toast、Log 提示以及 Java 与 C# 字符串互转等常用桥接能力,同时整理了获取 App 列表、判断服务与应用是否运行、打开/安装/卸载 App、发送广播,以及读取 WiFi 状态、安卓版本、原生类型 ID 和内置 SD 卡路径等实用封装。资源共 45 个文件,以 cs 脚本、asset 配置、meta 与 xml 清单为主,另含 jar 包和 unity 场景,压缩包约 48KB,结构紧凑便于直接导入工程参考。目前已有 743 人学习,适合作为 Unity 调用原生安卓的入门对照与二次封装起点。

1. 先别被“原生”吓到:Unity 调 Android 到底在调什么

如果你刚开始用 Unity 做安卓项目,大概率会遇到一个很具体的困惑:游戏逻辑跑得好好的,一旦要接支付、拿系统电量、调震动、读剪贴板、拉起某个系统设置页,就突然卡住了。Unity 自己那套 API 覆盖不到这些系统层面的能力,于是你搜到了“Unity 调用原生安卓”这个词。听起来像要同时精通两套完全不同的技术,其实入门阶段你只需要搞懂一件事:Unity 负责画面和逻辑,安卓原生负责跟系统打交道,两者之间开一扇门,互相递东西。

这扇门就是入门要学的全部核心。你可以把它想成一家餐厅:Unity 是前厅,负责接待客人、点单、上菜;安卓原生是后厨,负责处理只有后厨才有的设备。前厅服务员不会自己炒菜,但他知道怎么把订单递进窗口,也知道怎么把菜端出来。你要学的不是炒菜,而是“递订单”和“端菜”这两个动作。这份入门参考工具集,就是帮你把这套递送流程跑通的最小集合,适合完全没碰过安卓原生、但已经会用 Unity 做基础项目的新手。

2. 为什么值得学:三个你迟早会撞上的场景

2.1 场景一:Unity 商店里找不到的系统能力

Unity 的跨平台能力很强,但它为了保持各平台一致,主动放弃了很多“只有某个系统才有”的功能。比如你想让手机在特定时刻震动一下,Unity 有Handheld.Vibrate(),但它只能做最基础的震动,时长、强度、节奏都控制不了。再比如你想读取当前设备的电量百分比,Unity 根本没有对应 API。这些缺口不是 Unity 做得不好,而是它故意不做的——它不想为每个平台都维护一套系统级接口。

这时候你只有两条路:要么去 Asset Store 找一个别人封装好的插件,要么自己写一小段安卓代码,通过 Unity 提供的桥接机制调用。前者省事但受制于人,后者入门一次、终身受用。我刚开始学的时候也觉得“自己写原生”是遥不可及的事,后来发现入门只需要理解三个文件之间的关系,后面都是重复这个模式。

2.2 场景二:接第三方 SDK 时绕不开的桥

做安卓项目,迟早要接第三方 SDK,比如广告、统计、登录、支付。这些 SDK 几乎都只提供安卓原生接口,文档里全是 Java 或 Kotlin 代码。Unity 官方虽然有一些封装好的包,但版本更新慢,遇到问题很难排查。如果你懂一点 Unity 调原生的基础,就能自己写一层薄薄的桥接,把 SDK 的能力暴露给 Unity 的 C# 脚本。

这层桥接不需要你成为安卓专家。入门阶段你只需要会写一个静态方法,接收几个参数,返回一个结果。剩下的复杂逻辑,SDK 自己会处理。很多新手卡住不是因为技术难,而是因为不知道“从哪里开始改”。这份工具集的价值就在于,它把“从哪里开始”这件事给你标出来了。

2.3 场景三:性能敏感操作需要绕开 Unity 层

有些操作在 Unity 层做会非常慢,比如大量文件读写、复杂图像处理、加密解密。这些操作如果放到安卓原生层用 Java 或 Kotlin 实现,再通过桥接把结果传回 Unity,性能会好很多。入门阶段你不需要优化性能,但你需要知道“这条路是通的”。等你以后遇到性能瓶颈,至少知道有一个方向可以尝试,而不是对着 Unity Profiler 干瞪眼。

提示:入门阶段不要一上来就追求性能最优。先把“能调通”放在第一位,跑通之后再考虑优化。

3. 动手之前:把环境这关先过了

3.1 你需要准备的三样东西

第一样是 Unity Hub 和任意一个 2021 LTS 或更新的 Unity 版本。版本不用太新,LTS 版本最稳。第二样是 Android Build Support 模块,在 Unity Hub 里安装编辑器时勾选上,包括 SDK、NDK、OpenJDK 三件套。第三样是一个能打开安卓工程的编辑器,推荐 Android Studio,也可以用 VS Code 加安卓插件,但 Android Studio 对新手更友好,报错信息更清楚。

这三样东西装好之后,先别急着写代码。打开 Unity,新建一个 3D 项目,切换到 Android 平台,点一下 Build,确认能打出一个空的 APK。这一步看起来毫无意义,但它能帮你排除 90% 的环境问题。我第一次学的时候跳过这一步,结果后面调不通,花了整整一个下午才发现是 NDK 路径没配好。血泪经验:先让空项目跑起来,再动桥接代码。

3.2 理解三个文件夹的分工

Unity 项目里跟安卓原生相关的文件,主要放在三个地方。第一个是Assets/Plugins/Android,这里放编译好的.aar包或者.jar包,Unity 打包时会自动把它们塞进最终的 APK。第二个是Assets/Scripts,这里放你的 C# 脚本,负责调用原生方法。第三个是安卓工程本身,通常你会在 Android Studio 里单独建一个模块,写 Java 或 Kotlin 代码,编译成.aar后放回第一个文件夹。

入门阶段你不需要同时维护三个文件夹。最简单的做法是:先在 Android Studio 里写一个极简的安卓库,编译出.aar,拖进 Unity,然后在 C# 里调用。这个流程走通一次,后面就是复制粘贴改方法名的事。

3.3 第一个能跑通的例子:让安卓原生返回一个字符串

下面这个例子不接任何 SDK,不碰任何系统权限,只做一件事:Unity 调用安卓原生方法,原生返回一个字符串,Unity 打印出来。麻雀虽小,五脏俱全,桥接的完整链路都在里面。

先在 Android Studio 里新建一个 Empty Activity 项目,然后新建一个 Java 类:

package com.example.myplugin; public class MyPlugin { // 静态方法,Unity 通过类名和方法名直接调用 public static String getMessage() { return "Hello from Android Native"; } }

这段代码里,package是包名,后面 Unity 调用时要对应上。public static是必须的,Unity 只能调用静态方法。方法返回一个字符串,没有参数,这是最简单的形式。

编译出.aar文件,把它放到Assets/Plugins/Android目录下。然后在 Unity 里新建一个 C# 脚本:

using UnityEngine; public class NativeBridge : MonoBehaviour { void Start() { // 获取安卓原生类,参数是包名加类名 using (AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin")) { // 调用静态方法,返回值是字符串 string message = pluginClass.CallStatic<string>("getMessage"); Debug.Log("原生返回:" + message); } } }

AndroidJavaClass是 Unity 提供的桥接类,构造参数必须是完整的包名加类名。CallStatic<string>表示调用一个静态方法,并且返回值是字符串。如果方法没有返回值,就用CallStatic不带泛型。把脚本挂到场景里任意一个物体上,打包到安卓手机运行,Logcat 里就能看到那行输出。

注意:这段代码只能在安卓真机或模拟器上运行,在 Unity 编辑器里会报错。调试时要么打包看 Logcat,要么在 C# 里加平台判断,编辑器里跳过调用。

4. 避坑指南:新手最容易翻车的五个地方

4.1 坑一:类名或包名写错,报 ClassNotFoundException

现象是运行时报ClassNotFoundException,或者 Unity 控制台直接红字。原因通常是AndroidJavaClass里的字符串跟 Java 文件里的package和类名不一致。比如 Java 里写的是com.example.myplugin.MyPlugin,C# 里写成了com.example.MyPlugin,大小写差一个字母就找不到。

解决办法是复制粘贴,不要手敲。从 Java 文件第一行的package开始复制,加上类名,直接粘到 C# 里。改完之后重新打包,不要只在编辑器里试。

4.2 坑二:方法不是静态的,调用直接崩

现象是调用时抛出异常,提示方法不存在或者参数不匹配。原因是 Unity 的CallStatic只能调用静态方法。如果你的 Java 方法忘了加static,Unity 就找不到它。入门阶段所有给 Unity 调用的方法都写成public static,不要用实例方法。

解决办法是检查 Java 方法签名,确保有public static。如果确实需要实例方法,得先创建对象,但入门阶段不建议这么做,容易把自己绕进去。

4.3 坑三:参数类型对不上,传进去变成乱码

现象是方法能调用,但传过去的字符串变成乱码,或者数字变成奇怪的值。原因是 C# 和 Java 的类型系统不完全一样,比如 C# 的int对应 Java 的int没问题,但 C# 的string传到 Java 里需要用AndroidJavaObject包装,不能直接传。

解决办法是入门阶段只传基本类型:int、float、bool、string。字符串直接传通常没问题,但如果遇到乱码,检查编码格式,确保两边都是 UTF-8。复杂对象先不要碰。

4.4 坑四:忘了在 AndroidManifest 里加权限

现象是调用某个系统功能时直接闪退,Logcat 里提示Permission Denied。原因是安卓系统对敏感操作需要声明权限,比如读通讯录、访问相机、获取位置。Unity 打包时会生成一个默认的AndroidManifest.xml,但不会自动帮你加权限。

解决办法是在Assets/Plugins/Android下新建一个AndroidManifest.xml,把需要的权限加进去。入门阶段先不要碰需要权限的功能,从震动、剪贴板、电量这些不需要权限的开始。

4.5 坑五:在编辑器里测试原生调用

现象是 Unity 编辑器里点运行,直接报错说找不到安卓类。原因是AndroidJavaClass只在安卓运行时存在,编辑器是 Windows 或 Mac 环境,根本没有安卓虚拟机。这是新手最容易郁闷的地方,因为编辑器里测试最快,但偏偏测不了。

解决办法是养成习惯:写原生调用时,先用#if UNITY_ANDROID && !UNITY_EDITOR包起来,编辑器里走一个模拟分支,真机上走原生分支。这样编辑器里不会报错,真机上也能正常调。

void Start() { #if UNITY_ANDROID && !UNITY_EDITOR using (AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin")) { string message = pluginClass.CallStatic<string>("getMessage"); Debug.Log("原生返回:" + message); } #else Debug.Log("编辑器环境,跳过原生调用"); #endif }

这段代码在编辑器里打印“跳过”,在真机上打印原生返回的字符串。平台判断是入门阶段必须养成的习惯,能帮你省下大量排查时间。

5. 下一步学什么:从跑通一个方法到能接一个 SDK

跑通上面那个返回字符串的例子之后,你已经跨过了最难的门槛。接下来不要急着学复杂的东西,按这个顺序往下走,每一步都只比上一步多一点点。

第一步,把返回值从字符串换成整数,再从整数换成布尔值。感受一下CallStatic<int>和CallStatic<bool>的写法差异。第二步,给 Java 方法加上参数,比如传一个整数进去,返回整数加一。感受参数怎么从 C# 传到 Java。第三步,写一个没有返回值的方法,比如让安卓原生弹一个 Toast 提示。感受CallStatic不带泛型的写法。第四步,把这三个方法合并到一个类里,编译一次.aar,在 Unity 里依次调用。这一步走完,你就掌握了桥接的基本模式。

再往后,你可以尝试接一个真实的 SDK。选一个最简单的,比如只提供初始化、展示、回调三个接口的广告 SDK。先写一个 Java 类,把 SDK 的方法包一层静态方法,编译成.aar,再在 C# 里调用。遇到回调怎么办?入门阶段先用轮询,C# 每隔几秒调一次 Java 的“获取状态”方法。等熟练了再学AndroidJavaProxy做真正的回调。

下面这张表是我建议的练习顺序,每一步都对应一个具体能力,不要跳步:

步骤练习内容检验标准
1无参数返回字符串真机 Logcat 能看到输出
2带参数返回整数传入 1 返回 2
3无返回值弹 Toast真机屏幕弹出提示
4合并到一个类一次编译,三个方法都能调
5接一个简单 SDK能初始化并拿到回调状态

最后说一个我自己的习惯。从那以后我每次新建安卓桥接,都强制先写一个ping方法,不传参数,只返回一个固定字符串。打包到真机,确认这个字符串能打印出来,再开始写真正的业务逻辑。这个习惯帮我排除了无数次“到底是桥接没通还是业务代码写错”的纠结。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询