【Unity3d】Unity与Android之间通信
在unity开发或者sdk开发经常遇到unity与移动端原生层之间进行通信,这里把它们之间通信做一个整理。
关于Unity与iOS之间通信,参考【Unity3d】Unity与iOS之间通信
Unity(c#)调用Android
(一)、编写Java代码
实际上,任何已经存在的Java代码都可以被c#调用,不像iOS中需要事先用extern "C"修饰。
例如,Java中的MyJavaClass内容如下:
package com.devnn.demo;public class MyJavaClass{private static MyJavaClass instance=new MyJavaClass();public static getInstance(){return instance;}public String test(String param){return "This message is from Android!"}
}
getInstance和test是可以被c#调用的。
如果是kotlin写的代码,也是可以被c#调用的,要注意类路径,最好查看字节码或者反编译成Java查看路径。
另外,用了kotlin之后,需要额外添加kotlin运行时库,例如:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20"
为了方便导出jar或者aar,建议在library工程中编写。
(二)、将Java代码打包成aar或jar,拷贝到unity工程中
将打包好的aar或者jar拷贝到Unity工程的Assets目录或子目录中。
实际上拷贝到unity工程的Assets目录下的任意位置都可以,aar和jar会自动被unity作为lib依赖。(从导出gradle工程后可以看得出来)
(笔者使用的unity版本是2019.4,以前的版本不知道是否可以是任意位置。)
为了方便管理,以上aar/jar一般放在Assets/Plugins/Android中。
(三)、在c#中调用Java代码
c#中提供了两个类可以调用Java代码:
AndroidJavaClass.cs
AndroidJavaObject.cs
它们都在UnityEngine命名空间中。
AndroidJavaClass是继承自AndroidJavaClass。
这两个类的区别一般我们用不着,使用其中任意一个都可以。
使用方式很简单,在构造方法中传入Java类的完整路径,然后调用Call方式调用Java实例方法或者CallStatic调用Java的静态方法。方法泛型中写Java返回的类型。
示例代码:
//实例化AndroidJavaClass,传入Java类路径AndroidJavaClass jc = new AndroidJavaClass("com.devnn.demo.MyJavaClass");//如果找不到Java类,返回nullif(jc == null) return; //调用Java类的getInstance方法获取实例AndroidJavaObject jo = jc.CallStatic<AndroidJavaObject>("getInstance");//如果找不到Java方法,返回nullif (jo == null) return;string param = "Hello,Android!";string result = jo.Call<string>("test", param); //调用test方法,返回值是字符串。
Android调用Unity(c#)
Android调用c#比较简单,使用以下方法即可。
UnityPlayer.UnitySendMessage("MyTestObject", "TestFunc","msg");
需要依赖unity的classes.jar,位置在unity安装目录:AndroidPlayer/Variations/mono/Release/Classes/classes.jar。
Unity工程导出Android工程时,默认已经依赖了这个jar,自己新建的Android工程需要导入上述jar包。
这个unity的classes.jar目前不是开源的,反编译看到是混淆后的代码。
UnitySendMessage方法的源码如下:
//com.unity3d.player.UnityPlayer.classpublic static void UnitySendMessage(String var0, String var1, String var2) {if (!n.c()) {g.Log(5, "Native libraries not loaded - dropping message for " + var0 + "." + var1);} else {try {nativeUnitySendMessage(var0, var1, var2.getBytes("UTF-8"));} catch (UnsupportedEncodingException var3) {}}}private static native void nativeUnitySendMessage(String var0, String var1, byte[] var2);
可见,这是通过jni实现的。
第一个参数var0表示unity中物体GameObject的名字,注意不是c#脚本的名称也不是类名。
如下图:

第二个参数var1表示这个物体挂载的c#脚本中方法的名字。
第三个参数表示var2表示这个方法接收的数据。
例如,以上物体MyTestObject挂载了MyScript.c#脚本(如上图),MyScript.c#中有一个TestFunc方法:
using UnityEngine;public class MyScript : MonoBehaviour
{private void TestFunc(string content){//这里是接收Android调用的实现} }
那么在Android中调用UnitySendMessage("MyTestObject", "TestFunc", "msg") c#的TestFunc方法就会执行。
如果有多个参数需要发送,推荐使用json格式。
相关文章:
【Unity3d】Unity与Android之间通信
在unity开发或者sdk开发经常遇到unity与移动端原生层之间进行通信,这里把它们之间通信做一个整理。 关于Unity与iOS之间通信,参考【Unity3d】Unity与iOS之间通信 Unity(c#)调用Android (一)、编写Java代码 实际上,任何已经存在的Java代码…...
Allegro如何更改DRC尺寸大小操作指导
Allegro如何更改DRC尺寸大小操作指导 在做PCB设计的时候,DRC可以辅助设计,有的时候DRC的尺寸过大会影响视觉,Allegro支持将DRC的尺寸变小或者改大 如下图,DRC尺寸过大 如何改小,具体操作如下 点击Setup选择Design Parameters...
Mongodb WT_PANIC: WiredTiger library panic
文章目录故障现象排查过程1.查看Log2.同步恢复数据故障现象 周五突然收到Mongo实例莫名奇妙挂了告警,一般都是RS复制集架构模式(5节点),查看此实例角色为SECONDAR,挂了暂时不影响线上业务,但还是需要尽快修…...
【HTML】HTML 表格总结 ★★★ ( 表格标签 | 行标签 | 单元格标签 | 表格标签属性 | 表头单元格标签 | 表格标题标签 | 合并单元格 )
文章目录一、表格标签组成 ( 表格标签 | 行标签 | 单元格标签 )二、table 表格属性 ( border 属性 | align 属性 | width 属性 | height 属性 )三、表头单元格标签四、表格标题标签五、合并单元格1、合并单元格方式2、合并单元格顺序3、合并单元格流程六、合并单元格示例1、原始…...
linux013之文件和目录的权限管理
用户、组、文件目录的关系: 简介:用户和组关联,组合文件目录关联,这样就实现了用户对文件的权限管理。首先来看一下,一个文件或目录的权限是怎么查看的,ls -l, 如下,这个信息怎么看呢…...
设计模式之状态模式
什么是状态模式 状态模式是指允许一个对象在其内部状态改变时改变他的行为,对象看起来似乎改变了整个类。 状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状…...
XQuery 选择 和 过滤
XML实例文档 我们将在下面的例子中继续使用这个 "books.xml" 文档(和上面的章节所使用的 XML 文件相同)。 在您的浏览器中查看 "books.xml" 文件。 选择和过滤元素 正如在前面的章节所看到的,我们使用路径表达式或 FL…...
室友打了一把王者的时间,我理清楚了grep,find,管道|,xargs的区别与联系,用的时候不知道为什么要这样用
目录 问题引入 find和grep的基本区别 xargs命令 Linux命令的标准输入 vs 命令行参数 举例总结 问题引入 在自己做项目的过程中,想使用linux命令统计下一个目录下html文件的数量,在思考应该使用grep还是find去配合wc指令统计文件数量,后来…...
python 刷题时常见的函数
collections.OrderedDict 1. move_to_end() move_to_end() 函数可以将指定的键值对移动到最前面或者最后面,即最左边或最右边 。 2. popitem() popitem()可以完成元素的删除操作,有一个可选参数last(默认为True),…...
Python之列表推导式和列表排序
Python中的列表推导式,是小编比较喜欢的一种,他能大大减少你的代码量来得到你想要的结果,下面说说列表中常用的几种推导式 列表排序 Python开发中会经常用到排序操作,这里提供两种方式供大家参考,对象的sort()方法和…...
力扣(LeetCode)240. 搜索二维矩阵 II(C++)
题目描述 枚举 枚举整个矩阵,找到等于 target 的元素,则 return true ,否则 return false。 class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n matrix.size(), m matrix[0]…...
golang defer
文章目录延迟函数的参数在defer语句出现时就已经确定下来了延迟函数没有入参时,延迟函数体内的变量会受到影响延迟函数 *可以* 修改主函数的 *具名* 返回值延迟函数 *无法* 修改主函数的 *匿名* 返回值defer会把声明的 延迟函数以及 函数的入参放到栈上,…...
【Java】线程的死锁和释放锁
线程死锁是线程同步的时候可能出现的一种问题 文章目录1. 线程的死锁1.1 基本介绍1.2 应用案例2. 释放锁2.1 下面的操作会释放锁2.2 下面的操作不会释放锁1. 线程的死锁 1.1 基本介绍 多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,…...
如何使用断点续传上传大文件
概念 大文件上传的需求介绍 不管怎样简单的需求,在量级达到一定层次时,都会变得异常复杂。 文件上传简单,文件变大就复杂 上传大文件时,以下几个变量会影响我们的用户体验 服务器处理数据的能力请求超时网络波动 上传时间会变长…...
【图神经网络】图拉普拉斯滤波器如何实现全通、低通、高通滤波
【图神经网络】图拉普拉斯滤波器如何实现全通、低通、高通滤波 文章目录【图神经网络】图拉普拉斯滤波器如何实现全通、低通、高通滤波1. 前言2. 符号说明3. 三种滤波3.1 全通滤波3.2 低通滤波3.2.1 平滑信号分析3.2.2 广义拉普拉斯平滑滤波器3.3 高通滤波4. 总结1. 前言 GCN&…...
python操作mysql数据库详解
使用Python操作MySQL数据库 MySQL是一种关系型数据库管理系统,它可以用来存储和管理大量的数据。之前介绍了大部分主流数据库,今天将介绍如何使用Python来操作MySQL数据库。 安装MySQL 首先,我们需要安装MySQL服务器,可以从MyS…...
netty群聊系统
1设计思路:启动一个服务端,多个客户端第一个客户端启动时,会告诉服务器上线了第二个客户端启动时,告诉服务器上线,并且通知第一个启动的客户端第三个客户端启动时,告诉服务器上线,并且通知第一个…...
Android 初代 K-V 存储框架 SharedPreferences,旧时代的余晖?
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 前言 大家好,我是小彭。 SharedPreferences 是 Android 平台上轻量级的 K-V 存储框架,亦是初代 K-V 存储框架,至今被很多应用沿用。 有的…...
在windows中使用tomcat搭建Jenkins
1、 准备环境:JDK JDK官网下载:https://download.oracle.com/java/19/latest/jdk-19_windows-x64_bin.msi 2、 tomcat包 tocat官网下载:https://tomcat.apache.org/download-90.cgi 3、 Jenkins.war包 Jenkins官网下载:https://mi…...
Linux系统
linux系统 世界上最重要的服务器端操作系统。 创建新目录 mkdir app mkdir -m 目录权限 目录名 创建有权限的目录名。 创建一个空白文件 touch app.txt创建一个文件。 cat创建一个文件。 vi/vim创建一个文件。 nano创建一个文件。 truncate创建一个文件。 pwd查看当前目录。 rm…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
