Unity与Android交互通信系列(1)

news2024/11/23 20:54:23

  运行于Android平台的原生App直接调用Android接口,可以享受近水楼台先得月的优势,而使用Unity开发的Android应用App则像是二等公民,使用Android原生功能特性就要麻烦得多,比如WiFi、蓝牙等,特别是一些高级功能特性,Unity中没有完全覆盖,直接在Unity中开发显得力不从心,而且,Unity为适应跨平台开发部署需求,其引擎架构设计要复杂灵活得多,基于Unity引擎开发的App应用运行于独立的VM(Virtual Machine,虚拟机)中(采用IL2CPP后端编译的应用,运行时仍然需要虚拟机支持),这给App应用与Android原生系统代码的交互带来了困难。在实际应用开发中,基于Unity的App应用与底层的Android平台之间经常有交互需求,本系列我们主要学习Unity引擎与Android平台的交互通信。

(一) Android与Unity通信原理

  Unity引擎最大的优势和特点是一次制作、多端部署,极大的减轻了多平台游戏的开发和维护成本,而Unity引擎实现强大跨平台能力的基础是Mono / IL2CPP,Mono / IL2CPP是Unity引擎跨平台的核心和根本。

  在2001年,电信标准组织ECMA制定了一个与特定语言无关的跨体系结构的运行环境CLI(Common Language Infrastructure,公共语言基础)标准规范,只要使用规范定义的高级语言进行开发、应用程序符合CLI规范即可以确保在不同的计算机体系结构上实现跨平台运行。在此基础上,微软公司根据标准实现了.NET Framework公共语言运行时(Common Language Runtime,CLR),因此CLR是CLI的一个实现,.NET Framework即是一个运行于CLR基础上的框架,它支持C#、VB.NET、C++、Python等语言,但由于.NET Framework与Windows的深厚渊源,.NET Framework本身并不能跨平台。

  Mono则是Xamarin公司主导的另一个CLI实现,它通过内置C#语言编译器、CLR运行时和各类基础类库,可以使应用程序运行在Windows、Linux、FreeBSD、Android、iOS等各种平台上,因此,通过Mono能使用C#语言编写Android或iOS应用程序。在CLI规范中,高级语言并不是直接被编译成机器字节码,而是编译成中间语言(Intermediate Language,IL),这是一种介于高级言与机器字节码之间的与特定底层硬件无关的语言,在真正需要执行的时候,IL会被加载到Mono VM中[ Unity支持C#、Unity Script、Boo三种脚本开发语言,所有高级语言都会被编译成IL中间语言。],由VM动态的编译成机器码再执行(Just In Time,JIT编译),其执行过程如图1(a)图所示。
在这里插入图片描述

图1 Mono编译运行代码与IL2CPP编译运行代码流程示意图
  通过Mono,Unity引擎能够将应用部署到各类不同的系统平台上,实现跨平台运行。但由于IL在Mono VM中运行,而Mono VM是与系统平台紧密相关的,无法实现跨平台,所以Unity需要维护各种平台数量众多的Mono VM,并且JIT编译方式也降低了应用程序的运行速度,因此,Unity引擎引入了IL2CPP后端编译方式,通过将IL重新编译成C++代码,再由各类平台的C++编译器直接编译成原生汇编代码(Ahead Of Time,AOT编译),从而提升代码执行效率,并可利用各平台的C++编译器执行编译期间的优化,但由于高级动态语言的特性,内存管理和回收仍然需要统一维护,即需要IL2CPP VM负责GC、线程等服务性工作,但此时IL2CPP VM不再负责IL加载和动态解析,维护VM的工作量大为降低。


  虽然IL2CPP最后是采用AOT方式直接编译成各平台原生机器码,但其继承了IL中间语言的机制,对上层语言几乎没有影响(因为C++是静态语言,采用AOT方式编译,JIT动态语言的一些特性将不再可用),但它也需要借助VM进行内存管理等工作,如图1(b)所示。Android原生应用采用Java语言编写,Java语言也是先编译为Bytecode IL中间语言,然后依赖Android上的dalvik / art虚拟机解释执行。所以Unity引擎与Android原生代码交互通信实际是两个VM之间的通信,如图2所示。虽然Unity代码与Android原生代码在不同的VM中执行,但它们都处于同一个进程中,因此可以共享数据。

在这里插入图片描述

图2 Unity与Android交互通信示意图
  在图2中,Unity引擎通过UnityEngine提供的API调用Android方法,Android则借助于com.unity3d.player包提供的API调用Unity方法。通过这种方式,Unity引擎可以直接调用Android类及对象的方法,而Android则只能调用Unity中指定GameObject所挂载的脚本的方法,或者通过动态代理的方式调用Unity引擎中的方法。

  在执行层面,UnityEngine封装了AndroidJavaObject、AndroidJavaClass、AndroidJavaProxy类,通过这几个类就可以获取Android端静态类或者动态对象,从而可以执行其相应方法;Android则是通过Unity应用的mainActivity与C#代码通信[ 本节讲述的Unity与Android的交互通信实质上是指C#代码与Java代码、JAR包、AAR包、SO包的相互调用,但遵循习惯描述为Unity引擎与Android操作系统软件之间的通信。]。

  Activity是Android应用中最基本和最重要的组件之一,其作用类似于web中的page、winform中的form,因此,只有活跃的Activity才能响应输入,所以,Android代码首先要通过com.unity3d.player.UnityPlayer包下的currentActivity获取到活跃Activity,利用其与Unity代码通信。

(二) Unity直接调用Java代码

  Unity2018之后的版本统一使用Gradle进行Android端的编译、构建和打包,而Android Studio也使用Gradle进行编译、构建和打包,即它们都使用同一种编译构建工具,也即是Java代码与C#代码都可以在Unity中被正确的编译到Android端,这就为在Unity中直接使用Java与C#语言打下了基础。

  而且为方便映射Java数据结构,在UnityEngine类中还内置了若干封装好的类,其中最重要的类有:AndroidJavaClass、AndroidJavaObject、AndroidJavaProxy,这些类是进行Java端与C#端相互调用的基础。AndroidJavaClass是java.lang.Class类在Unity中的表达,主要用于类结构反射、获取类静态属性或者调用类静态方法,其公共方法如表1所示。

表1 AndroidJavaClass公共方法列表
公共方法调用对象/属性类型泛型方法描述
Call非静态Call调用对象非静态方法
CallStatic静态CallStatic调用类静态方法
Get非静态Get获取对象非静态属性
GetStatic静态GetStatic获取类静态属性
Set非静态Set设置对象的非静态属性
SetStatic静态SetStatic设置类静态属性
GetRawClass-GetRawClass获取原生Java类型的指针,用于JNI
GetRawObject-GetRawObject获取原生Java对象的指针,用于JNI
Dispose--IDisposable接口回调

  AndroidJavaObject是java.lang.Object类在Unity中的表达,而java.lang.Object类是Java中所有类的基类,因此其能接受所有的Java对象,其公共方法如表2所示。

表2 AndroidJavaObject公共方法列表
公共方法调用对象/属性类型泛型方法描述
Call非静态Call调用对象非静态方法
CallStatic静态CallStatic调用类静态方法
Get 非静态Get获取对象非静态属性
GetStatic静态GetStatic获取类静态属性
Set非静态Set设置对象的非静态属性
SetStatic静态SetStatic设置类静态属性
GetRawClass-GetRawClass获取原生Java类型的指针,用于JNI
GetRawObject-GetRawObject获取原生Java对象的指针,用于JNI
Dispose--IDisposable接口回调
  通过表1和表2可以看到,这两个类公共方法完全一样,这就为开发者使用这两个类提供了完全一致的使用外观。 在使用中,通过AndroidJavaClass类的forName()方法、.class属性生成相应类的对象,由于Class类方法常用于反射,所以一般用于调用对应类的静态属性或者方法;AndroidJavaObject表示对象,通过其getClass()方法可以获取该对象的类型,所以一般用于调用对象的实例方法或者属性。例如有一个类com.davidwang.util,其有一个静态方法StaticMethod(),一个实例方法InstanceMethod(),则new AndroidJavaClass("com.davidwang.util").callstatic("StaticMethod")等同于调用util.StaticMethod();而new AndroidJavaObject("com.davidwang.util").call("InstanceMethod")等同于 new Util().InstanceMethod()。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1310760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角

本节课的内容,就让我们来学习一下ArrayList集合的应用,ArrayList的本质就是一个顺序表,那下面一起来学习吧 目录 一、杨辉三角 1.题目详情及链接 2.剖析题目 3.思路及代码 二、洗牌算法 1.创造牌对象 2.创造一副牌 3.洗牌操作 4.发…

大数据笔记(待续)

mysql 缓存技术 数据库和缓存双写数据一致性问题常见的解决方案 常见方案通常情况下,我们使用缓存的主要目的是为了提升查询的性能。大多数情况下,我们是这样使用缓存的: 用户请求过来之后,先查缓存有没有数据,如果有…

学习笔记 -- CAN系统基础

一、CAN物理层 一个双节点CAN网络示意图如下,两颗120Ω终端电阻并联呈现总线电阻60Ω。 A、B两个节点的CAN收发器(Transceiver),只负责电平转换。当总线静默时,收发器内部的2.5V电源经15KΩ电阻把CAN-H和CAN-L都拉到2.…

前端(一):HTML+CSS

参考课程:23最新版web前端开发_哔哩哔哩_bilibili 文档:GitHub - codeNiuMa/HTML-md-file: 学习HTML课程时的资料 目录 1 HTML 1.1 骨架 DOCTYPE html标签 head标签 body标签 title标签 meta标签 1.2 标签标题h1 1.3 段落p 1.4 水平线 1.5 图片img 1.6 …

【Android12】Android Framework系列--AMS启动Activity分析

AMS启动Activity分析 通过ActivityManagerService(AMS)提供的方法,可以启动指定的Activity。比如Launcher中点击应用图标后,调用AMS的startActivity函数启动应用。 AMS提供的服务通过IActivityManager.aidl文件定义。 // frameworks/base/core/java/an…

【AI底层逻辑】——数学与机器学习:优雅的智慧之舞

目录 “宝藏网站” 聊聊数学 “华尔兹” “智慧之舞” 后续的章节我们将迎来新的篇章,新的切入点探索AI的奥秘,通过揭示高数、矩阵、概率论等数学知识与机器学习的关系来深入理解AI的奥秘! “宝藏网站” 开头先给大家上几个宝藏网站&am…

【离散数学】——期末刷题题库(欧拉图和哈密顿图)

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

java中,用函数对象表示策略

简而言之,函数指针的主要用途就是实现策略(Strategy)模式。 Java没有提供函数指针,但是可以用对象引用实现相同的功能。调用对象上的方法通常是执行该对象上某项操作。 在Java中,使用函数对象(Function Object)表示策…

《数据结构、算法与应用C++语言描述》-机器调度-最长处理时间(LPT)

机器调度 完整可编译运行代码见:Github::Data-Structures-Algorithms-and-Applications/_28LongestProcessingTime 问题描述 一个工厂具有 m台一模一样的机器。我们有n 个任务需要处理。设作业i的处理时间为 t i t_i ti​,这个时间包括把作业放入机器…

Amazon Aurora Limitless Database:数据库管理的全新境界

授权说明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 亚马逊云科技开发者社区, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道 在当今数亿用户、PB级数据和数百万交易的业务环境中,数…

12.14_黑马数据结构与算法笔记Java

目录 120 二叉搜索树 min max 121 二叉搜索树 put 122 二叉搜索树 前任后任1 123 二叉搜索树 前任后任2 124 二叉搜索树 删除1 125 二叉搜索树 删除2 126 二叉搜索树 删除3 127 二叉搜索树 删除 递归1 128 二叉搜索树 删除 递归2 129 二叉搜索树 范围查询 130 二叉搜…

KUKA机器人如何隐藏程序或程序段?

KUKA机器人如何隐藏程序或程序段? 如下图所示,新建一个示例程序进行说明, 如下图所示,如果红框中的动作指令不想让别人看到,想隐藏起来,如何做到? 如下图所示,在想要隐藏的程序或程序段的前后,分别添加 ;fold 和 endfold指令(这里要注意是英文状态下的输入法), 如…

国标GB28181安防监控系统/磁盘阵列EasyCVR(V.3.4)新亮点:免保活功能

TSINGSEE青犀近日发布了EasyCVR安防管理平台的V.3.4版本,其中一大亮点就是很多朋友都在咨询的“免保活”功能,那么,什么是“免保活”功能?又该如何配置呢? 在EasyCVR平台有个【按需直播】按钮,顾名思义&…

如何部署Portainer容器管理工具+cpolar内网穿透实现公网访问管理界面

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 本文主要介绍如何本地安装Portainer并结合内网穿透工具实现任意浏览器远程访问管理界面。Portainer 是一个轻量级…

大象elephant目标检测数据集VOC+YOLO格式2300张

大象是长鼻目象科的哺乳动物,有两个属,是世界上最大的陆生动物。其像柱子一样的四肢和宽厚的脚掌可以稳稳支撑住庞大的身体。巨大的头上长有蒲扇状的大耳朵和长且有弹性的鼻子。象耳上有丰富的血管,可以有效散热。鼻子和上唇合而为一的象鼻由…

YB9225是一种固定工作频率的高效率电流模式升压转换器。

YB9225B 1.2 MHz。峰值5A 电流,升压转换器 概述 : YB9225是一种固定工作频率的高效率电流模式升压转换器。YB9225集成了一个非常低的 Rds-on NMOSFTET,以减少功率损耗和实现高效率。最高效率可达93% 。功率 MOSFET 的峰值电流限制在5 A。1.…

网站使用CDN后无法获取用户真实IP的解决方法

宝塔或Nginx环境 如果你使用的宝塔或Nginx,可以在宝塔面板或Nginx中,找到配置文件增加如下代码后,重载配置或者重启 Nginx 即可: #CDN获取真实ip set_real_ip_from 0.0.0.0/0; real_ip_header X-Forwarded-For; PHP语言函数方法…

36、什么是池化算法

池化算法也是 CNN 网络中非常常见的算法。 池化这一算法理解起来比较简单,从名字中或许可以看到一些东西:从一个像素池子中选取一些有代表性的像素出来。 常见的池化有最大池化和平均池化。最大池化就是从像素池子中选取最大值出来,而平均池化就是从像素池子中选取平均值出…

HTML---初识CSS

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.CSS概念 CSS是层叠样式表(Cascading Style Sheets)的缩写。它是一种用于描述HTML文档外观样式的标记语言。通过CSS,开发者可以在不改变HTML标记结构的情况…

机器学习 | 机器学习基础知识

一、机器学习是什么 计算机从数据中学习规律并改善自身进行预测的过程。 二、数据集 1、最常用的公开数据集 2、结构化数据与非结构化数据 三、任务地图 1、分类任务 Classification 已知样本特征判断样本类别二分类、多分类、多标签分类 二分类:垃圾邮件分类、图像…