【Flutter】【Unity】使用 Flutter + Unity 构建(AR 体验工具包)

news2024/10/3 10:36:09

使用 Flutter + Unity 构建(AR 体验工具包)【翻译】

原文:https://medium.com/potato/building-with-flutter-unity-ar-experience-toolkit-6aaf17dbb725
在这里插入图片描述

由于屡获殊荣的独立动画工作室 Aardman 与讲故事的风险投资公司 Fictioneers(Potato、Tiny Rebel Games 和 Sugar Creative 的联盟)之间的合作,Wallace & Gromit:The Big Fix Up 于 2021 年 1 月推出。

该免费应用可在英国、美国和加拿大的 iOS 和 Android 设备上使用,它创造了一种叙事驱动的体验,带领用户体验 AR 游戏、CG 动画、角色内电话、扩展现实 (XR) 门户和漫画 带子。 在新的故事情节中,发明家华莱士和他的狗格罗米特的新企业签订了一份“修复”英国布里斯托尔市的合同。

The Big Fix Up 应用程序公开已经三个月了,它获得了很多关注。 这个基于 Flutter with Unity 构建的 AR 杰作是同类产品中的首创,并且对我们构建这种实时讲故事体验的方法提出了许多有趣的问题:

  • 为什么要颤振?
  • 在 Flutter 中嵌入 Unity3D 应用程序?
  • Unity 与 Flutter 的通信
  • 将 Unity 嵌入 Flutter 的性能影响,
  • 应用程序包大小等

下面我们就来分解一下我们是如何回答这些问题,并最终解决了 Unity 嵌入 Flutter 的问题。 结果是一个 Flutter Unity View 插件,它在此处为社区开源发布:
https://github.com/juicycleff/flutter-unity-view-widget

为什么要颤振?
如果您在移动应用程序开发或工程领域,您很可能不需要介绍 Flutter,但如果不需要,

Flutter 是 Google 的开源工具包,用于从单个代码库为移动、Web、桌面和嵌入式设备构建漂亮的本地编译应用程序。

Flutter 使移动开发人员能够以最小的努力构建令人惊叹的、高性能的、漂亮的应用程序,并使用可满足您几乎所有需求的小部件。
Learn more about Flutter.

在测试了几个流行的移动跨平台框架之后,我们选择了 Flutter,原因有 3 个:

  • 表现
  • 稳定
  • 丰富的用户界面

性能和稳定性是我们非常关心的问题,因为我们的应用程序是 Flutter 应用程序和 Unity 应用程序的组合。 在其他跨平台框架上进行测试时,我们遇到了 Unity 无法正确渲染,或者有时在很多设备上渲染空白等问题。

此外,与 Flutter 相比,框架(其他跨平台)和 Unity 之间的双向通信在发送时相对较慢,例如向 Unity 发送 Touch 和 Gesture 事件,但使用 Flutter,我们对与 Unity 之间更高效的事件通知和消息通信进行了基准测试 只有纯原生移动开发才能与之匹敌。 Flutter 渲染功能非常强大,我们在其上渲染我们的 Unity 应用程序时从未遇到过任何问题,而且由于 Flutter 小部件是周围最漂亮、最引人注目的库存 UI 组件,因此在 Flutter 中制作漂亮的应用程序并不费力。

在 Flutter 中嵌入 Unity3D 应用程序

我们需要将 Unity 项目导出为本机 iOS 和 Android 项目,以便我们可以将其转换为本机包,可以将其添加到我们的 Flutter 应用程序的本机代码库中。 问题是 Unity 当时只支持将 Unity 项目导出为应用程序而不是包(这是 UaaL 之前的版本)。 这需要对实际的 Unity 项目进行修改,这在很大程度上涉及修改我们导出的 Unity 应用程序源并将其转换为库。 但是今天支持 Unity 作为一个库 (UaaL),它现在确实更好地支持在本机应用程序中重用 Unity,几乎不需要做任何修改,但我们仍然需要一些类似的东西;

当 Unity 播放器准备好在 Flutter 中使用时通知 Flutter。 例如,我们通过像这样扩展代码库向 Unity iOS 后构建处理器添加了一个新的通知事件。

/// <summary>
/// Edit 'UnityAppController.mm': triggers 'UnityReady' notification after Unity is actually started.
/// </summary>
private static void EditUnityAppControllerMM(string path)
{
    var inScope = false;
    var markerDetected = false;

    EditCodeFile(path, line =>
    {

        inScope |= line.Contains("- (void)startUnity:");
        markerDetected |= inScope && line.Contains(TouchedMarker);

        if (inScope && line.Trim() == "}")
        {
            inScope = false;

            if (markerDetected)
            {
                return new string[] { line };
            }
            else
            {
                return new string[]
                {
                    "    // Modified by " + TouchedMarker,
                    @"    [[NSNotificationCenter defaultCenter] postNotificationName: @""UnityReady"" object:self];",
                    "}",
                };
            }
        }

        return new string[] { line };
    });

}

我们还必须通过将所有 Gradle android 应用程序相关代码替换为 android 库来自动修改 Gradle 构建脚本,从而修改 Unity 项目 Android 导出以无缝地与 Flutter 一起工作;

public static void DoBuildAndroid()
{
    ...

    // Modify build.gradle
    var build_file = Path.Combine(androidExportPath, "build.gradle");
    var build_text = File.ReadAllText(build_file);
    build_text = build_text.Replace("com.android.application", "com.android.library");
    build_text = build_text.Replace("bundle {", "splits {");
    build_text = build_text.Replace("enableSplit = false", "enable false");
    build_text = build_text.Replace("enableSplit = true", "enable true");
    build_text = build_text.Replace("implementation fileTree(dir: 'libs', include: ['*.jar'])", "implementation(name: 'unity-classes', ext:'jar')");
    build_text = Regex.Replace(build_text, @"\n.*applicationId '.+'.*\n", "\n");
    File.WriteAllText(build_file, build_text);

    // Modify AndroidManifest.xml
    var manifest_file = Path.Combine(androidExportPath, "src/main/AndroidManifest.xml");
    var manifest_text = File.ReadAllText(manifest_file);
    manifest_text = Regex.Replace(manifest_text, @"<application .*>", "<application>");
    Regex regex = new Regex(@"<activity.*>(\s|\S)+?</activity>", RegexOptions.Multiline);
    manifest_text = regex.Replace(manifest_text, "");
    File.WriteAllText(manifest_file, manifest_text);

    ...
}

知道我们可以自动从 Unity 导出并即时修改 Unity 导出后,Unity 就可以嵌入到 Flutter 中了。 这为 Flutter 渲染 unity 打下了良好的基础。 借助 Flutter 中对高性能原生扩展的支持,我们能够使用 Flutter Native API 实现在 Flutter 上渲染 Unity,其中一些是;

  • PlatformView
  • FlutterPlugin
  • FlutterPlatformViewFactory

这些 API 使我们能够在 Flutter 中为 Android 和 iOS 平台附加 Unity 原生视图。 在不影响渲染的情况下,我们需要在 Flutter 和 Unity 之间进行完全双向通信。

Unity 与 Flutter 的通信

Flutter 确实支持通过 MethodChannel API 支持从 Flutter 到本机端的高性能消息传输,这是 Flutter 优于其他跨平台框架的一个很好的原因。 MethodChannel API 为我们提供了与本机代码通信的方式,但是,作为库的 Unity 仅允许单向通信,即仅从 Flutter 到 Unity,因此我们必须弄清楚 Unity 如何向 Flutter 发送消息。 幸运的是,Unity 支持从 Unity 内部调用本机代码类和静态方法,这导致编写了 Unity 消息管理器,其工作是调用 Kotlin/Java/Obj C/Swift 静态类方法,这反过来通知或调用 Flutter 方法 . Unity 消息管理器看起来像这样;

public class NativeAPI
{
    #if UNITY_IOS && !UNITY_EDITOR

    [DllImport("__Internal")]
    public static extern void OnUnityMessage(string message);
    #endif


    public static void SendMessageToFlutter(string message)
    {
        #if UNITY_ANDROID
        try
        {
            AndroidJavaClass jc = new AndroidJavaClass("com.xraph.plugin.flutter_unity_widget.UnityPlayerUtils");
            jc.CallStatic("onUnityMessage", message);
        }
        catch (Exception e)
        {
            Debug.Log(e.Message);
        }
        #elif UNITY_IOS && !UNITY_EDITOR
        NativeAPI.OnUnityMessage(message);
        #endif
    }
}

在这里,我们在使用 CSharp 预处理器指令时调用原生 Android 类 UnityPlayerUtils 方法 UnityPlayerUtils 和 ObjectiveC 静态方法 NativeAPI.OnUnityMessage(message)。 在 Flutter 原生端,Android Kotlin 的方法看起来像这样;

class UnityPlayerUtils {
  ...
  /**
  * Invoke by unity C#
  */
  @JvmStatic
  fun onUnityMessage(message: String) {
    for (listener in mUnityEventListeners) {
        try {
            listener.onMessage(message)
        } catch (e: Exception) {
            e.message?.let { Log.e(LOG_TAG, it) }
        }
    }
  }
  ...
}

在 iOS 上就这么简单;

void OnUnityMessage(const char* message)
{
    [UnityPlayerUtils unityMessageHandler:message];
}

并调用Flutter MessageChannel实例通知flutter;

@objc public class UnityPlayerUtils: UIResponder, UIApplicationDelegate, UnityFrameworkListener {
  @objc
  public static func unityMessageHandler(_ message:        UnsafePointer<Int8>?) {
    if let strMsg = message {
        globalChannel?.invokeMethod("events#onUnityMessage", arguments: String(utf8String: strMsg))
    } else {
        globalChannel?.invokeMethod("events#onUnityMessage", arguments: "")
    }
  }
}

有了这些,我们通过 MethodChannel API 在 Flutter 和 Unity 之间进行了双向通信,性能非常出色,这对我们最初选择 Flutter 至关重要。

将 Unity 嵌入 Flutter 的性能影响

在 Flutter 上渲染 Unity 非常像在原生视图中渲染原生视图,就是这么高效! Unity 在 Flutter 中的性能没有性能问题,您只需要通过确保卸载 Unity 或在不与 Unity 场景交互时处于资源较少的场景中来管理 Unity CPU 和内存使用情况。

在您的 AR 项目中使用 Flutter 和 Unity

最后,Unity 和 Flutter 的结合非常适合您的下一个 AR 项目,因为您可以将 Flutter 的漂亮 UI 与简单而强大的游戏引擎相结合,从而拥有一个真正的非游戏移动应用程序,同时具有游戏引擎的可能性。 我们在这里公开了 Flutter Unity 集成包,因此您不必从头开始。 就在这里,祝你下一个项目好运。

  • Github: https://github.com/juicycleff/flutter-unity-view-widget

  • Pub: https://pub.dev/packages/flutter_unity_widget

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

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

相关文章

最大公约数:常用的四大算法求解最大公约数,分解质因数法、短除法、辗转相除法、更相减损法。

常用的四大算法求解最大公约数&#xff0c;分解质因数法、短除法、辗转相除法、更相减损法。 (本文获得CSDN质量评分【91】)【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#x…

网络基础-虚拟化工具-网桥

系列文章目录 本系列文章主要是回顾和学习工作中常用的网络基础命令&#xff0c;在此记录以便于回顾。 该篇文章主要是讲解虚拟化的工具网桥相关的概念和常用命令 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录系…

C++之多态【详细总结】

前言 想必大家都知道面向对象的三大特征&#xff1a;封装&#xff0c;继承&#xff0c;多态。封装的本质是&#xff1a;对外暴露必要的接口&#xff0c;但内部的具体实现细节和部分的核心接口对外是不可见的&#xff0c;仅对外开放必要功能性接口。继承的本质是为了复用&#x…

MySQL(主从、半同步、组复制、MHA高可用)

文章目录一、MySQL源码编译以及初始化二、mysql主从复制、半同步MySQL组复制MySQL读写分离MHA高可用一、MySQL源码编译以及初始化 源码编译使用cmake&#xff0c;所以要提前安装cmake&#xff0c;完成之后make install即可 这里要创建mysql用户&#xff0c;以及用普通用户方式…

电子秤专用模拟数字(AD)转换器芯片HX711介绍

HX711简介HX711是一款专为高精度电子秤而设计的24 位A/D 转换器芯片。与同类型其它芯片相比&#xff0c;该芯片集成了包括稳压电源、片内时钟振荡器等其它同类型芯片所需要的外围电路&#xff0c;具有集成度高、响应速度快、抗干扰性强等优点。降低了电子秤的整机成本&#xff…

分享112个JS菜单导航,总有一款适合您

分享112个JS菜单导航&#xff0c;总有一款适合您 112个JS菜单导航下载链接&#xff1a;https://pan.baidu.com/s/1Dm73d2snbu15hZErJjTXxg?pwdfz1c 提取码&#xff1a;fz1c Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "h…

【游戏逆向】RPG游戏背包镶嵌系统分析

镶嵌系统是很多3D游戏都有的功能&#xff0c;玩家可以向镶嵌槽内附加宝石来提升装备的属性&#xff0c;这也直接提升了物品的价值。在一些扫拍卖和摆摊的外挂中经常利用这个属性来低价购入高价值装备。以这款游戏为例&#xff0c;我们来对装备上的镶嵌槽和镶嵌宝石进行分析。 …

Nacos,一款非常优秀的注册中心(附视频)

Nacos 核心源码精讲 - IT贱男 - 掘金小册全方位源码精讲&#xff0c;深度剖析 Nacos 注册中心和配置中心的核心思想。「Nacos 核心源码精讲」由IT贱男撰写&#xff0c;375人购买https://s.juejin.cn/ds/BuC3Vs9/ 先简单说两句 你好&#xff0c;很高兴你能够点开本小册&#x…

python 的 if 语句如何使用说明

文章目录1. 一个示例2. 条件测试2.1 检查是否相等2.2 检查是否相等时不考虑大小写2.3 检查是否不相等2.4 比较数字2.5 检查多个条件2.6 布尔表达式3. if 语句4. 使用 if 语句处理列表1. 一个示例 关于 if 条件语句的使用&#xff0c;我们来写一个示例进行说明&#xff1a; #写…

6.14 Rayleigh商

定义 矩阵在某个向量处的瑞利商Rayleigh quotient是这样定义的: ρ(x):xHAxxHx\rho(x) :\frac{x^HAx}{x^Hx} ρ(x):xHxxHAx​   这个怎么理解呢?上面是埃尔米特内积的表达式&#xff0c;下面是标准埃尔米特内积。但是矩阵不一定是对称阵&#xff0c;如果不是复数的话&#x…

ChatGPT 这个风口,普通人怎么抓住:比如APP集成ChatGPT,公众号集成ChatGPT...

文章目录1. 引出问题2. 简单介绍ChatGPT2.1 ChatGPT是什么2.2 如何使用ChatGPT3. 普通人利用ChatGPT 变现方式1. 引出问题 最近几天OpenAI发布的ChatGPT聊天机器人如日中天&#xff0c;连着上了各个平台的热搜榜。 很多平台也都已集成了ChatGPT&#xff0c;比如csdn的客户端A…

json-server使用

文章目录json-server使用简介安装json-server启动json-server操作创建数据库查询数据增加数据删除数据修改数据putpatch配置静态资源静态资源首页资源json-server使用 简介 github地址 安装json-server npm install -g json-server启动json-server json-server --watch db…

Linux系统位运算函数以及相应CPU ISA实现收录

以32位数据的二进制表示为例&#xff0c;习惯的写法是LSB在左&#xff0c;MSB在右&#xff0c;注意BIT序和大小端的字节序没有关系。Linux和BIT操作有关的接口在定义在头文件bitops.h中&#xff0c;bitops.h定义有两层&#xff0c;通用层和架构层&#xff0c;对应两个bitops.h&…

【重要】2023年上半年有三AI新课程规划出炉,讲师持续招募中!

2023年正式起航&#xff0c;想必大家都已经完全投入到了工作状态中&#xff0c;有三AI平台今年将在已有内容的基础上&#xff0c;继续进行新课程开发&#xff0c;本次我们来介绍今年上半年的课程计划&#xff0c;以及新讲师招募计划。2023年新上线课程我们平台的课程当前分为两…

【Python爬虫案例】批量采集网站壁纸,实现自动更换桌面壁纸

前言 美照天天换&#xff0c;才不会腻 不知道你们是不是这样&#xff0c;我的手机壁纸电脑壁纸&#xff0c;隔三岔五就喜欢换&#xff0c;看久了 我就腻了&#xff0c;索性就用python把这个网站的壁纸都采集下来&#xff0c;顺便再让电脑自动更换我的桌面壁纸 ~ 一篇文章教会…

【AI简报第20230210期】 ChatGPT爆火背后、为AIoT和边缘侧AI喂算力的RISC-V

1. ChatGPT爆火背后&#xff1a;AI芯片迎接算力新挑战原文:https://www.163.com/dy/article/HT7BHN3C05199NPP.htmlChatGPT的出圈走红为AIGC打开全新市场增量&#xff0c;催生了更高的算力需求。作为人工智能三大核心要素之一&#xff0c;算力也被誉为人工智能“发动机”。华泰…

使用服务器搭建alist和webdav

docker镜像官网&#xff1a;https://hub.docker.com/r/xhofe/alist 一、准备工作 环境&#xff1a;centos7、docker 二、步骤 1.拉取alist镜像 在根目录下执行以下命令&#xff1a; docker pull xhofe/alist:latest2.运行alist docker run -d --restartalways -v /etc/ali…

互联网医院源码 线上问诊 智慧医院源码 C#源码

互联网医院平台源码 智慧医院管理系统源码 开发环境&#xff1a;ASP.NET C# VS2019 SQL2008 依托于实体医院利用互联网技术对接院内业务信息系统&#xff0c;向患者提供基于线上问诊、预约挂号、缴费结算、医患互动、诊后随访、健康科普和复诊等全面的医疗健康互联网服务。…

一文读懂 Zebec Chain 的“先行网络” Nautilus 链

最近&#xff0c;Zebec上线了DAO治理系统后&#xff0c;上线并通过了关于Nautilus链的提案&#xff0c;这也是DAO系统上线后通过的首个提案。Nautilus链可以被看作是Zebec Chain上线前的“先行”链&#xff0c;并且是目前行业内为数不多的以“Layer3”作为特点的模块化通用链&a…

花2到5块钱注册体验chatgpt

最近很火的chatGPT不对中国开放&#xff0c;简直太坑了。不过网上也有很多例子去如何注册&#xff0c; 1. 需要可以上网的非中国IP。 有梯子的也可以&#xff0c; 我是某宝3块钱租了一个一天体验的国外服务器&#xff0c;可以查阅资料&#xff0c;有需要可以直接去淘。 2.一个…