当前位置: 首页 > news >正文

【Unity3D】Unity与Android交互

1 Unity 发布 apk

1.1 安装 Android Build Support

        在 Unity Hub 中打开添加模块窗口,操作如下。

        选择 Android Build Support 安装,如下(笔者这里已安装过)。 

         创建一个 Unity 项目,依次点击【File→Build Settings→Android→Switch Platform】,配置如下。

        依次点击【Edit→Preferences→External Tools】打开 JDK、SDK、NDK、Gradle 配置页面,配置如下(勾选默认配置就行,也可以选择已安装的 JDK、SDK、NDK、Gradle路径)。

1.2 配置密钥

        依次点击【Edit→Project Settings→Player→Keystore Manager】(也可以从【File→Build Settings→Player Settings→Keystore Manager】中进入),操作如下。

        打开 Keystore Manager 后, 依次点击【Create New→Anywhere】,选择一个目录保存密钥库文件,笔者保存在项目目录下面的【Keystore/user.keystore】中。

        接着设置密码和别名,其他选项不是必设项。

        Add Key 后,会弹出“是否将创建的密钥库作为项目的密钥库”弹窗,点击 yes 确认。

         设置密钥后,回到 Project Settings 页面,显示如下。

        创建密钥时,也可以通过以下命令创建。

keytool -genkey -keyalg RSA -alias key_name -keystore keystore_name -validity day_time
keytool -genkey -keyalg RSA -alias first -keystore user -validity 36500

1.3 打包 apk

        依次点击【File→Build Settings→Player Settings】,配置公司名、项目名、版本号等信息,如下。

        在 Other Settings 中配置包名、Android SDK 的最小 API 版本、目标 API 版本等信息,如下。 

        关闭 Player Settings,在 Build Settings 页面点击底部的 Build,构建 apk。 

1.4 案例

        新建一个 Unity 项目,修改 Game 页面的屏幕尺寸,如下。

        搭建页面如下。

        给 Button 按钮添加脚本,如下。

        Test.cs

using UnityEngine;
using UnityEngine.UI;public class Test : MonoBehaviour {private Button button;private void Start() {button = GetComponent<Button>();button.onClick.AddListener(OnClick);}private void OnClick() {Debug.Log("Test-OnClick");}
}

        编译 apk 后,打开命令行窗口,输入以下命令安装到手机上。

adb instll -r -t -d Test.apk

        运行 apk 后,在命令行窗口中通过以下命令查看日志。

adb logcat | findstr "Test-OnClick"

         点击 Button 按钮,打印日志如下。

2 Unity 调 Android 的逻辑

2.1  Unity 项目中部署 Android 代码

        1)拷贝 Java 源码到 Unity 项目

        可以将 Android 项目中 Java 代码拷贝到 Unity 项目中 Assets 子目录下,如下,接着就可以通过 AndroidJavaClass 或 AndroidJavaObject 访问 Java 代码了。

        2)打包 Jar 到 Unity 项目

        可以将 Android 项目打包为 Jar,再将 Jar 拷贝到 Unity 项目中 Assets 子目录下,接着就可以通过 AndroidJavaClass 或 AndroidJavaObject 访问 Java 代码了。

        修改 Android 项目中 Module 的 build.gradle 文件,如下,主要将 id 由 'com.android.application' 修改为 'com.android.library',删除 android { } 模块中的 defaultConfig、buildTypes、compileOptions 子模块。

        build.gradle

plugins {id 'com.android.library'
}android {namespace 'com.zhyan8.test'compileSdk 33
}dependencies {implementation 'androidx.appcompat:appcompat:1.6.1'implementation 'com.google.android.material:material:1.8.0'implementation 'androidx.constraintlayout:constraintlayout:2.1.4'testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.5'androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

        修改 build.gradle 文件后,需要点击右上角的 Sync Now 同步,接着按以下步骤编译项目。

        编译结束后,在 Module 的【build\intermediates\aar_main_jar\debug】目录下生成打包的 classes.jar。

        预览 classes.jar 文件如下。

2.2 AndroidJavaObject 和 AndroidJavaClass

        AndroidJavaObject 和 AndroidJavaClass 是 Unity 提供的调用 Java 代码的 2 个类,AndroidJavaClass 继承 AndroidJavaObject,它们只有构造方法有一点差异,没有其他的差异,因此,本节只介绍 AndroidJavaObject。

        1)Set 和 Get 属性

        JavaTest.java

package com.zhyan8.test;public class JavaTest {public static int intVal = 0;private String strVal = "abc";
}

        UnityTest.cs

using UnityEngine;public class UnityTest : MonoBehaviour {private void Start() {AndroidJavaObject javaObject = new AndroidJavaObject("com.zhyan8.test.JavaTest");// 静态属性Set/GetjavaObject.SetStatic<int>("intVal", 123);int intVal = javaObject.GetStatic<int>("intVal");Debug.Log("UnityTest, intVal=" + intVal); // 打印: UnityTest, intVal=123// 非静态属性Set/GetjavaObject.Set<string>("strVal", "xyz");string strVal = javaObject.Get<string>("strVal");Debug.Log("UnityTest, strVal=" + strVal); // 打印: UnityTest, strVal=xyz}
}

        说明:对于 JavaTest 的 private 属性,AndroidJavaObject 也可以访问到。

        2)调用方法

        JavaTest.java

package com.zhyan8.test;import android.util.Log;public class JavaTest {public static void fun1() {Log.d("JavaTest", "fun1"); // 打印: JavaTest: fun1}private int fun2() {Log.d("JavaTest", "fun2"); // 打印: JavaTest: fun2return 123;}public String fun3(int value) {Log.d("JavaTest", "fun3, value=" + value); // 打印: JavaTest: fun3, value=235return "Call fun3";}public String fun4(String value1, int value2) {Log.d("JavaTest", "fun4, value1=" + value1 + ", value2=" + value2); // 打印: JavaTest: fun4, value1=abc, value2=123return value1 + value2;}
}

        说明:对于 JavaTest 的 private 方法,AndroidJavaObject 也可以访问到。  

        UnityTest.cs

using UnityEngine;public class UnityTest : MonoBehaviour {private void Start() {AndroidJavaObject javaObject = new AndroidJavaObject("com.zhyan8.test.JavaTest");// 静态方法javaObject.CallStatic("fun1");// 非静态无参方法int val2 = javaObject.Call<int>("fun2");Debug.Log("UnityTest, val2=" + val2); // 打印: UnityTest, val2=123// 非静单参方法string val3 = javaObject.Call<string>("fun3", 235);Debug.Log("UnityTest, val3=" + val3); // 打印: UnityTest, val3=Call fun3// 非静双参方法string val4 = javaObject.Call<string>("fun4", "abc", 123);Debug.Log("UnityTest, val4=" + val4); // 打印: UnityTest, val4=abc123}
}

        运行程序后,打印日志如下。

2.3 Unity 调用 Android 的 Toast

        UnityTest.cs

using UnityEngine;
using UnityEngine.UI;public class UnityTest : MonoBehaviour {private void Start() {GetComponent<Button>().onClick.AddListener(() => {Toast("Clicked", 1);});}// 调用Android的代码: Toast.makeText(context, msg, durationFlag).show();private void Toast(string msg, int durationFlag) { // durationFlag: Toast.LENGTH_SHORT=0, Toast.LENGTH_LONG=1AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");AndroidJavaObject toast = toastClass.CallStatic<AndroidJavaObject>("makeText", currentActivity, msg, durationFlag);toast.Call("show");}
}

        UnityPlayer 是 Unity 引擎提供的 Java 类。

3 Android 调 Unity 的逻辑

3.1 Unity 打包为 Android 项目

        在 Build Settings 页面勾选 Export Project 后,点击 Export 按钮,如下。

        构建成功后,Unity 项目将会被打包成一个 Android 项目,我们可以使用 Android Studio 打开生成的 Android 项目。

D:\Program Files\Unity Hub\Unity\Editor\2021.3.11f1c2\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar

3.2 Unity 打包为 aar

相关文章:

【Unity3D】Unity与Android交互

1 Unity 发布 apk 1.1 安装 Android Build Support 在 Unity Hub 中打开添加模块窗口&#xff0c;操作如下。 选择 Android Build Support 安装&#xff0c;如下&#xff08;笔者这里已安装过&#xff09;。 创建一个 Unity 项目&#xff0c;依次点击【File→Build Settings→…...

信号去噪算法

引言 在实际世界中&#xff0c;我们所获得的信号通常都包含了各种干扰和噪音。这些噪音可能来自电子设备、环境条件或传感器本身&#xff0c;它们会损害信号的质量&#xff0c;降低信息提取的准确性。因此&#xff0c;信号去噪和降噪技术在科学、工程和医学领域中扮演着至关重…...

GPT带我学-设计模式-10观察者模式

1 请你介绍一下观察者模式 观察者模式&#xff08;Observer Pattern&#xff09;是一种设计模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象&#xff08;被观察者&#xff09;的状态发生改变时&#xff0c;所有依赖于它的对象&#xff08;观察者&…...

JDK - 常用的设计模式

单例模式 &#xff1a; Runtime 类&#xff1a;Java 运行时环境是单例的&#xff0c;可以通过 Runtime.getRuntime() 方法获得实例。Calendar 类&#xff1a;Calendar.getInstance() 方法返回的是一个单例的 Calendar 实例。数据源连接池&#xff1a;连接池的管理通常采用单例模…...

华为OD机考算法题:寻找最大价值的矿堆

题目部分 题目寻找最大价值的矿堆难度难题目说明给你一个由 0&#xff08;空地&#xff09;、1&#xff08;银矿&#xff09;、2&#xff08;金矿&#xff09;组成的的地图&#xff0c;矿堆只能由上下左右相邻的金矿或银矿连接形成。超出地图范围可以认为是空地。 假设银矿价值…...

wf-docker集群搭建(未完结)

系列文章目录 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、redis集群二、mysql集群三、nacos集群1. 环境要求2. 拉取镜像2.1. 拉取镜像方式配置集群2.2. 自定义nacos镜像配置集群 3 自定义…...

uni-app 在 APP 端的版本强制更新与热更新

整包更新与热更新的区别 ① 整包更新是指下载完整 apk 文件进行覆盖安装 ② 热更新是指把 app 有改动的地方打包进 wgt 文件&#xff0c;只更新 wgt 文件中的内容&#xff0c;不进行整包安装&#xff0c;在用户视角也叫做省流量更新 版本号规则约束 建议严格遵循 Semantic …...

实在智能受邀参加第14届珠中江数字化应用大会,AI赋能智能制造,共话“湾区经验”

制造业是实体经济的主体&#xff0c;是技术创新的主战场&#xff0c;是供给侧结构性改革的重要领域。抢占新一轮产业竞争制高点&#xff0c;制造业的数字化转型已成为行业升级的必由之路。 10月21日&#xff0c;第14届“珠中江”&#xff08;珠海、中山、江门&#xff09;数字…...

Qt 窗口的尺寸

默认尺寸 对于一个Qt的窗口&#xff08;继承于QWidget&#xff09;&#xff0c;获取其窗体尺寸的方法size()&#xff1b; 以一个Qt创建Qt Widgets Application项目的默认生成代码为基础&#xff0c;做如下测试 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent…...

游戏数据分析对于运营游戏平台的重要性

游戏数据分析对于运营游戏平台具有至关重要的意义&#xff0c;它可以提供深入的见解&#xff0c;帮助了解玩家行为、偏好和互动&#xff0c;从而优化游戏体验&#xff0c;提高玩家参与度和留存率。 首先&#xff0c;通过游戏数据分析&#xff0c;运营者可以了解玩家在游戏中的表…...

微信群发消息的正确打开方式,让你的社交更高效!

在当今的社交媒体时代&#xff0c;微信已经成为了我们生活中必不可少的一部分。而微信的群发消息功能&#xff0c;让我们可以方便地将信息一次性发送给多个联系人。然而&#xff0c;微信的群发消息功能有一个限制&#xff0c;即每次只能群发200个联系人。这对于需要发送消息给大…...

HTML5语义化标签 header 的详解

&#x1f31f;&#x1f31f;&#x1f31f; 专栏详解 &#x1f389; &#x1f389; &#x1f389; 欢迎来到前端开发之旅专栏&#xff01; 不管你是完全小白&#xff0c;还是有一点经验的开发者&#xff0c;在这里你会了解到最简单易懂的语言&#xff0c;与你分享有关前端技术和…...

SpringCloud复习:(2)@LoadBalanced注解的工作原理

LoadBalanced注解标记了一个RestTemplate或WebClient bean使用LoadBalancerClient来进行负载均衡。 LoadBalancerAutoConfiguration类给带注解的RestTemplate添加了拦截器&#xff1a;LoadBalancerInterceptor. 具体流程如下&#xff1a; 首先定义一个LoadBalancerInterceptor…...

vue钩子函数以及例子

Vue.js 是一个基于组件化的前端框架&#xff0c;它提供了一些钩子函数&#xff0c;用于控制组件在不同阶段的行为和处理。以下是 Vue.js 常用的钩子函数以及它们的作用和示例&#xff1a; beforeCreate&#xff1a;在实例被创建之前调用。此时组件的数据、方法等还没有被初始化…...

redis场用命令及其Java操作

目录 1. Redis入门 1.1 Redis简介 1.2 Redis下载与安装 1.2.1 Redis下载 1.2.2 Redis安装 1.3 Redis服务启动与停止 1.3.1 服务启动命令 1.3.2 客户端连接命令 1.3.3 修改Redis配置文件 1.3.4 Redis客户端图形工具 2. Redis数据类型 2.1 五种常用数据类型介绍 2.2 …...

UG\NX二次开发 同时设置多个对象的高亮状态 UF_DISP_set_highlights

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 感谢粉丝订阅 感谢 captainliubang 订阅本专栏,非常感谢。 简介 UG\NX二次开发 同时设置多个对象的高亮状态 UF_DISP_set_highlights 效果 代码(在for循环中逐个设置多个对象…...

Qt+树莓派4B 手动设置系统日期和时间

文章目录 前言一、设置日期二、设置时间 前言 某些设备需要在无网络环境下工作,系统时间和日期无法通过网络实时同步,此时就需要人为设置. 一、设置日期 QString m_date,m_time;QDateEdit *dateEdit new QDateEdit(this); dateEdit->setFixedSize(250,60); connect(date…...

用大顶堆和小顶堆实现优先队列

大顶堆小顶堆&#xff08;或大根堆小根堆&#xff09; 利用大顶堆实现优先队列&#xff0c;所谓大顶堆&#xff0c;容器内部元素是有序的&#xff0c;而且是按从大到小排序的&#xff08;小顶堆刚好相反&#xff0c;从小到大&#xff09;。容器只有一个出口一个入口&#xff0…...

PDCA项目开发环境搭建说明

PDCA项目开发环境搭建说明 环境准备 JDK 15.0 &#xff1b; IDEA Community Edition 2021.3 版本要对应&#xff0c;不然会报错 Jdk 安装步骤&#xff1a;https://blog.csdn.net/qq_34913677/article/details/108894727 IDea 安装说明&#xff1a;https://blog.csdn.net/dream…...

Git简明教程

1.Git的定位 在我们自己开发项目的过程中&#xff0c;经常会遇到这样的情况&#xff0c;为了防止代码丢失&#xff0c;或者新变更的代码影响到原有的代码功能&#xff0c;为了在失误后能恢复到原来的版本&#xff0c;不得不复制出一个副本,比如&#xff1a;“坦克大战1.0”“坦…...

Boost ASIO 库深入学习(3)

Boost ASIO 库深入学习&#xff08;3&#xff09; UDP简单通信导论 在继续深入前&#xff0c;我们不妨也来点碎碎念&#xff0c;因为UDP通信协议的模型与TCP是不同的&#xff0c;这种差异正是理解“无连接通信”的关键所在。我们下面要构建的&#xff0c;是一个经典的UDP通信…...

vue中Echarts的使用

文章目录 Echarts概述什么是EchartsEcharts的好处 Vue中Echarts的使用Echarts的安装Echarts的引入 Echarts概述 什么是Echarts Apache ECharts&#xff1a;一个基于 JavaScript 的开源可视化图表库。 其官网如下&#xff1a;https://echarts.apache.org/zh/index.html Echar…...

【RAG召回】bge实现向量相似度索引

sentence-transformers 是一个非常强大的 Python 框架&#xff0c;它可以将句子或段落转换成高质量、高信息密度的数字向量&#xff08;称为“嵌入”或 Embeddings&#xff09;。它厉害的地方在于&#xff0c;语义上相似的句子&#xff0c;其向量在空间中的距离也更近。 这使得…...

OpenJudge | 大整数乘法

总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的积。 输入 有两行&#xff0c;每行是一个不超过200位的非负整数&#xff0c;没有多余的前导0。 输出 一行&#xff0c;即相乘后的结果。结果里不能有多余的前导0&#xff0c;即如果结果是342&am…...

【Vue3】(三)vue3中的pinia状态管理、组件通信

目录 一、vue3的pinia 二、【props】传参 三、【自定义事件】传参 四、【mitt】传参 五、【v-model】传参&#xff08;平常基本不写&#xff09; 六、【$attrs】传参 七、【$refs和$parent】传参 八、provide和inject 一、vue3的pinia 1、什么是pinia&#xff1f; pinia …...

深入浅出玩转物联网时间同步:基于BC260Y的NTP实验与嵌入式仿真教学革命

在万物互联的时代&#xff0c;精准的时间戳是物联网系统的神经节拍器&#xff0c;而NTP协议正是维持这一节律的核心技术。 一、时间同步&#xff1a;物联网世界的隐形基石 在智慧城市、工业4.0等场景中&#xff0c;分散的设备需要毫秒级的时间协同。网络时间协议&#xff08;N…...

⚡️ Linux Docker 基本命令参数详解

&#x1f433; Linux Docker 基本命令参数详解 &#x1f4d8; 1. Docker 简介 Docker 是一个开源的容器化平台&#xff0c;它通过将应用及其依赖打包到一个轻量级、可移植的容器中&#xff0c;从而实现跨平台运行。Docker 采用 C/S 架构&#xff0c;服务端称为 Docker Daemon&a…...

树莓派系统中设置固定 IP

在基于 Ubuntu 的树莓派系统中&#xff0c;设置固定 IP 地址主要有以下几种方法&#xff1a; 方法一&#xff1a;使用 Netplan 配置&#xff08;Ubuntu 18.04 及以上版本默认使用 Netplan&#xff09; 查看网络接口名称 在终端输入ip link或ip a命令&#xff0c;查看当前所使…...

MySQL 8.0 绿色版安装和配置过程

MySQL作为云计算时代&#xff0c;被广泛使用的一款数据库&#xff0c;他的安装方式有很多种&#xff0c;有yum安装、rpm安装、二进制文件安装&#xff0c;当然也有本文提到的绿色版安装&#xff0c;因绿色版与系统无关&#xff0c;且可快速复制生成&#xff0c;具有较强的优势。…...

如何做好一份优秀的技术文档:专业指南与最佳实践

如何做好一份优秀的技术文档&#xff1a;专业指南与最佳实践 技术文档是产品开发、用户支持和团队协作的核心工具。高质量的技术文档能够提升开发效率、降低维护成本并改善用户体验。本文将从实践出发&#xff0c;详细讲解如何编写专业、清晰且实用的技术文档。 &#x1f31f;…...