Unity的Addressables使用体验

之前大致的了解了Addressalbe这个插件的大致功能和原理,并没有深入的使用。刚好这段时间有时间,就按照具体的项目场景搭建了一个简单的框架来体验。我是用它跟XLua来搭建整个游戏的框架的。Addressables的版本是1.22.3。我的体验也是围绕这个版本来讲的。使用的过程中发现它的下面几个问题,让我觉得目前还是不要在项目中使用它。 1.性能问题 通过标签一次性加载大量粒度很细的文件,会非常的慢。 Adressables可以通过lable标签来加载同一类型的资源。比如在项目中,把所有类型的lua文件都打上 <Lua> 标签。你可以选择 Addressables.LoadResourceLocationsAsync 先获取所有打了该标签的文件地址,然后再用一个循环去加载每一个地址的lua文件,然后把文件按照Key-Value的方式存在一个字典中。也可使用 Addressables.LoadAssetsAsync<Type>("key"), (asset)=>{} 方式按照标签加载所有的资源,然后在它里面的回调中去处理每一个lua文件,并保存到字典。这个回调每加载一个该标签下的文件,都会回调一次。 很显然,这个加载循环无法避免。由于lua文件的数量巨大,导致这个循环完成非常的耗时,比如在这次测试的项目中,总共有接近400个lua文件,总耗时在webgl平台达到惊人的 5.89 秒,并且随着功能的增多,这个数量只会往上加。这是很难接受的。android和IOS我没有测试,不过由于多线程的加持,估计是会比较快的。我们的主要平台是webgl. 2.工具黑盒 这个插件并不是开源的,对于用户来说,资源的下载,打包过程都是不受用户控制的。也就是说,它对用户来说是一个黑盒。他在官网有用户手册和API说明,但也就仅仅是那些而已。我甚至觉得这个东西不是为游戏开发者准备的,更像是一个功能说明。它的加载API少的非常的可怜,估计也就3个左右吧,不知道是不是我看的不够仔细,我真的没有再发现别的加载API了。而且API设计的很模糊,太多的功能细节集中到一个API上了,然后例子又少。虽然GitHub上有官方的示例,但我真的还是第一次见到如此模糊的API设计,我真的无法通过参数去了解该API到底能做什么事情。 用户没有办法了解其中具体的细节,也没有办法去定制项目需要的功能,万一有一些东西满足不了项目的需求需要修改,就只能干着急,你做不了任何事情。它的封装级别很高,但是对于游戏开发者来说,这过头了。这个插件更像是面向产品用来设计快速原型的产物。就拿上面的第一个问题来说,所有的lua其实已经打在一个AB包里面了,那么AB包下载之后,再从AB包中去加载lua文件,应该是非常的快的(毫秒级别),但不知道为什么,400多个文件加载居然要5.89秒,它里面是不是每一个文件加载都去走了什么特殊流程导致非常的慢。然后勾选了缓存,第二次,第三次,第四次的时间也是一样的,居然没有任何的时间减少。用户知道的太少了。 3.各种的小问题 我这里例举一个下载进度的问题。 public IEnumerator LoadAssetAsyn(string key, Action<Object> completeCB, Action<float> pgrFunc = null) { AsyncOperationHandle<Object> opHandle; opHandle = Addressables.LoadAssetAsync<Object>(key); while (opHandle.Status == AsyncOperationStatus.None) { Log.Error("Percent=" + opHandle.GetDownloadStatus().Percent + " pp=" + opHandle.PercentComplete); if (pgrFunc != null) { pgrFunc(opHandle.GetDownloadStatus().Percent); } yield return null; } yield return opHandle; if (opHandle.Status == AsyncOperationStatus.Succeeded) { Object instObj = Object.Instantiate(opHandle.Result); completeCB(instObj); if (pgrFunc != null) { pgrFunc(1); } } yield return null; } 上面的这个方法去加载一个资源,然后通过回调告诉目前的下载进度。opHandle.GetDownloadStatus().Percent 和 opHandle.PercentComplete 都不准确。前者是通过大小计算百分比,后者是通过数量计算百分比。 下面是文档的原话: AsyncOperationHandle.PercentComplete: Reports the percentage of sub-operations that have finished. For example, if an operation uses six sub-operations to perform its task, the PercentComplete indicates the entire operation is 50% complete when three of those operations have finished (it doesn’t matter how much data each operation loads). AsyncOperationHandle.GetDownloadStatus: Returns a DownloadStatus struct that reports the percentage in terms of total download size. For example, if an operation has six sub-operations, but the first operation represented 50% of the total download size, then GetDownloadStatus indicates the operation is 50% complete when the first operation finishes. ...

November 7, 2024 · 1 min · 188 words · LINK

Unity的Addressables学习日志

1.构建Player的时候,项目的资产数据是如何放进Player中的 由下图可以看出来Unity中的资产分成了4个主要类别: 1.被场景引用的资源 2.放在Resources文件夹中的资源 3.标记为了Addressables Group的资源 4.放在了StreamingAssets文件夹中的资源 2.如果同一个资产被划分到了不止一个类别上,那么该资产在构建的时候就会产生重复,划分了多少个就会复制多少个 3.Addressables Groups中的共享资产 对于一个标记为非Adressables的资产,如果有不止一个Adressablees的资产引用了它,那么它会在每个引用了它的Addressables的bundle中都复制一份。如下图所示: 为了消除这种复制,那么可以将这个共有的资产也标记为Addressables。然后把它引入到一个已存在的bundle中就可以了。如果此时一个bundle要引用它,那么必须在该bundle实例化前,将引入了共有资产的bundle先加载才可以。 4.Sprite的依赖 图集的引用跟其他资产不一样。 情形一 三张纹理,分别在三个不同的group中,它们会分别进入三个不同的ab包,彼此之间没有依赖,每个ab中图片的大小是500KB 情形二 还是这三张图片,它们被放进了一个图集,这个图集没有被标记为Addressables。那么包含这个图集的ab包将有图集的1500KB的大小。而另外两个ab包则只包含Sprite的元数据(只有很小的几KB),并且将包含图集的ab包列为自己的依赖。无论是哪个ab包包含这个图集,在重新构建之后都是跟前面一样的结果,这个过程由Unity控制,用户决定不了。这是跟标准的处理依赖重复资源过程的最大不同。Sprites的加载依赖它的图集,而图集的加载只依赖包含它的ab包的加载。 情形三 在上面的情形二的基础上,图集被标记成了Addressables并且单独放在它自己的图集中。这时候就会创建4个ab包。如果使用的是Unity2020.x或者更新的版本,那么在构建之后,4个ab包之间的依赖关系会和期待的一样,即图集资源在图集的这个ab包,有1500KB。另外三个ab包把图集的ab包作为依赖,只有几KB的引用数据而已。如果使用的是Unity2019.x或者更旧的版本,那么纹理资源就可能存在于这4个ab包中的某一个。另外三个ab包依然把图集所在的ab包作为依赖。然而此时图集所在的ab包可能仅仅只包含了图集的一些元数据,而真正的纹理资源可能在其他的另外3个ab包中。 5.Addressable预制体跟Sprite的依赖 情形一 跟三个标记为Addressables的纹理不同的是,这里是三个标记为Addressables的Sprite的预制体。每个预制体包含它独自的Sprite。在构建之后,三个ab包的大小如期望的那样,都是500KB。 情形二 跟情形一类似,3个预制体分别引用不同的Sprite,只不过所有的3个Sprite添加到一个图集中,但是这个图集没有标记为Addressables。在这种情形下,图集的纹理机会产生重复。在构建之后,三个ab包都大概有1500KB。这个重复资源的规则类似于一般的Addressables重复资源规则,但是跟前面介绍的 Sprite的依赖 中的情形二又不一样。 情形三 基于上面的情形二的预制体,纹理和图集,不过这里把图集标记为Addressables。此时图集纹理就仅仅只存在在包含图集的ab包中。另外的三个预制体的ab包就把这个图集的ab包作为依赖。 6.ab包的分包规则 1.可以将一个group中所有Addressables的资源都打进一个ab包中 2.可以将一个group中的每个Addressables资源分别打进它独自的ab包中 3.可以将使用同一个label的所有的Addressables资源打包进一个ab包中 7.同一个group中的场景资源会跟其他的Addressables资源分开打包 也就是说一个group中如果含有场景资源和其他非场景资源,那么构建之后,至少会得到两个bundle,一个包含场景资源,一个是除了场景外的其他资源。

August 29, 2023 · 1 min · 35 words · LINK

Ubuntu22.04运行unity2020.3.xx报错unity_csc.sh_Aborted

在Ubuntu22.04中出现,而且出现这个错误的版本是低于Unity2022.x的版本。自己测试了Unity2020.x和Unity2021.x都会出现这个错误。 重现的步骤也很简单,创建一个空项目并进入就会报错,然后提示进入safety mode。 这个错误会在Unity的Editor.log中留下线索,不过在打开项目前,记得先把Editor.log先删除,这样在报错的时候会生成一个新的Editor.log文件。也可以不用这样做,这样做的主要目的是日志少检查起来比较简单。 打开Unity编辑器的日志:Editor.log。发现以下关键信息 -----CompilerOutput:-stderr---------- No usable version of the libssl was found /home/eyap/Unity/Hub/Editor/2020.3.33f1/Editor/Data/Tools/RoslynScripts/unity_csc.sh: line 3: 25959 Aborted (core dumped) "/home/eyap/Unity/Hub/Editor/2020.3.33f1/Editor/Data/Tools/RoslynScripts/../../Tools/Roslyn/csc" /shared /noconfig @temp/UnityTempFi -----EndCompilerOutput--------------- 从 No usable version of the libssl was found 可以看出是缺少了 libssl库导致的。用下面的命令安装一个就行了: echo "deb http://security.ubuntu.com/ubuntu focal-security main" | sudo tee /etc/apt/sources.list.d/focal-security.list sudo apt-get update sudo apt-get install libssl1.1 相关的讨论连接: https://forum.unity.com/threads/unity2020-3-doesnt-works-on-linux.1338869/

August 29, 2023 · 1 min · 55 words · LINK

Xlua集成第三方库

XLua集成第三方库(Rapidjson举例) 参考教程:https://zhuanlan.zhihu.com/p/389424029 1.环境准备 (1)cmake的安装 https://cmake.org/download/ (2)安装Visual Studio最新版(2017,2019,2022)都行,去微软官网下载 (3)安卓的话,下载Android Studio,然后安装好Android SDK,NDK,并且配置好ANDROID_SDK和ANDROID_NDK 2.将XLua克隆到本地 xlua的地址 https://github.com/Tencent/xLua 进入到拉取下来的xlua文件夹, 在build文件夹中新建lua-rapidjson文件夹,并在该文件夹下新建include和source文件夹 4.拉取lua-rapidjson的项目到本地 这里需要说明一下,lua-rapidjson两个版本: 一个是原作者的最新版 https://github.com/xpol/lua-rapidjson 另一个是XLua的做过兼容的版本: https://github.com/chexiongsheng/build_xlua_with_libs 新版肯定是更新,但是再编译的过程中会遇到很多错误,非常的麻烦浪费时间,所以我们还是选择XLua做过兼容的版本,节省时间,并且也能满足要求。 将build_xlua_with_libs克隆到本地。 5,直接将build_xlua_with_libs中build文件夹下的lua-rapidjson文件夹复制到自己的xlua的build文件夹下面。 6.修改xlua/build/CMakeList.txt文件,在头部加入如下代码 #begin lua-rapidjson set (RAPIDJSON_SRC lua-rapidjson/source/rapidjson.cpp ) set_property( SOURCE ${RAPIDJSON_SRC} APPEND PROPERTY COMPILE_DEFINITIONS LUA_LIB ) list(APPEND THIRDPART_INC lua-rapidjson/include) set (THIRDPART_SRC ${THIRDPART_SRC} ${RAPIDJSON_SRC}) #end lua-rapidjson 并且把头部的VERSION 改成自己的cmake版本(在控制台输入cmake –version),我这里是cmake_minimum_required(VERSION 3.26.4) 6.编译windows的xlua.dll 这里我们选择lua54版本 所有编译脚本都是按这个方式命名:make_平台_lua版本.后缀。 比如windows 64位lua53版本是make_win64_lua53.bat,android的luajit版本是make_android_luajit.sh,要编译哪个版本就执行相应的脚本即可。 执行完编译脚本会自动拷贝到plugin_lua53或者plugin_luajit目录,前者是lua53版本放置路径,后者是luajit。 用代码编辑器打开这个bat文件,将Visual Studio版本改成自己安装的对应版本, 如果不知道就打开 Developer Command Prompt这个控制台,里面会有如图所示 ...

July 13, 2023 · 1 min · 211 words · Link

项目中Git要忽略的文件

项目中Git要忽略的文件 红框框起来的部分即为要忽略的文件 1 Unity项目中 要忽略的文件如下图: 2 Visual Studio项目中 要忽略的文件如下图:

April 22, 2022 · 1 min · 9 words · Link

在Unity的Hierarchy面板上添加鼠标右键菜单

在Unity的Hierarchy面板上添加右键菜单 这里添加的是复制一个模型的节点信息的功能,从子节点自身开始复制,一直到模型的父节点终止。因为有时候模型的子节点比较多,一个一个的去点开查找比较麻烦,或者想查看子节点的路径对不对。记得priority要写。 代码如下: public static class EditorTool { [MenuItem("GameObject/EditorTool/CopyPath", priority = 0)] static string CopyPath() { if (Selection.gameObjects.Length == 1) { GameObject selectObj = Selection.gameObjects[0]; StringBuilder pathSB = new StringBuilder(selectObj.name); while (selectObj.transform.parent != null) { pathSB.Insert(0, selectObj.transform.parent.name + "/"); selectObj = selectObj.transform.parent.gameObject; } GUIUtility.systemCopyBuffer = pathSB.ToString(); return pathSB.ToString(); } return ""; } }

May 25, 2021 · 1 min · 53 words · Link