还在用难用的AssetBundle?快来运用Unity新的可寻址资源系统,助力游戏开发
Unity Addressables可寻址资源系统是一个强大的Unity资源包,它能够帮助解决游戏开发中最重要的一些挑战:高效率和轻松的内容管理。
在管理游戏资源时,往往很难维持好的标准,从而避免让项目变得杂乱无章。最主要的问题在于不同职责的资源管理系统之间的耦合。而且,项目中资源的存储,加载和载入后资源的使用方法都有紧密的联系。

例如:我们可能要在Resources文件夹存储某个精灵。这会让Unity在构建版本时,把精灵存到特定的存档文件中。由于精灵存在了这样的位置,我们必须通过Resources API来加载该精灵。
项目变得混乱的速度比你想象的更快,一种方法的选择将造成项目长期的结果。一个好的系统会避免我们轻易犯下草率的错误,一个优秀的系统也会易于学习和使用。
通过使用Unity Addressables可寻址资源系统,我们可以将资源管理问题分离。我们的目标是保持灵活性,同时让项目具有可维护性。
本文,我们将介绍开发者使用Unity Addressables可寻址资源系统创作游戏时,会获得的三个好处。
好处1:减少游戏的内存压力
在发布游戏时,大多数平台都会让开发者提供玩游戏所需的最低硬件配置要求,以便玩家在购买时参考。
原因很简单:要求的硬件配置越高,购买游戏的玩家会越少。而从另一个角度看,实现的内存管理越好,我们便可在游戏提供更多内容和乐趣。
Unity Addressables可寻址资源系统的第一个好处便是:高效的内存管理。
为了大致了解其效果,我们可以把这些代码:
public class CharacterCustomization : MonoBehaviour
{
[SerializeField] private List<Material> _armorVariations;
[SerializeField] private MeshRenderer _armorRenderer;
public void ChangeArmorVariation(int variationId)
{
_armorRenderer.material = _armorVariations[variationId];
}
}
转化为下面的代码:
using UnityEngine.AddressableAssets;
public class CharacterCustomizationV2 : MonoBehaviour
{
[SerializeField] private List<AssetReference> _armorVariations;
[SerializeField] private MeshRenderer _armorRenderer;
public IEnumerator ChangeArmorVariation(int variationId)
{
var loadProcess = _armorVariations[variationId].LoadAssetAsync();
yield return loadProcess;
_armorRenderer.material = loadProcess.Result;
}
}
转化后实现的效果如下图所示,我们可以轻松节省内存使用。

了解使用可寻址资源系统实现更好内存管理的内容,请阅读:《使用Unity Addressables可寻址资源系统》。
好处2:轻松快捷地加入DLC内容
使用Unity Addressables的第二个好处:可以让开发者完全控制存储和加载游戏资源,从而有助于开发者添加和出售可下载内容(DLC)。
即使目前不考虑发布DLC内容,只要在项目中使用Addressables系统,我们就已经提前为这项工作做好了准备。
我们也有其它方法来出售DLC内容,例如:使用Asset Bundles,但这些方法在实现相同作用的同时,会带来更高的开销,因此这些方法会逐渐被弃用。维护正常运行的Asset Bundle管线非常消耗时间和精力,需要大量复杂的专业知识。
在Unity中有很多方法可以实现DLC内容,但对于初学者来说,下面代码是很好的学习起点:
public class DlcManager : MonoBehaviour
{
// ...
public IEnumerator TryDownloadDlc()
{
if (_hasBoughtDlc && _dlcDownloaded == false)
{
var operationHandle = Addressables.DownloadDependenciesAsync("DLC-Content");
while (operationHandle.IsDone == false)
{
_progressText.text = $"{operationHandle.PercentComplete * 100.0f} %";
yield return null;
}
}
}
}
通过以上代码,你应该了解其中的原理。我们能够使用Unity Addressables,通过少量成本为玩家带来更多乐趣,何乐而不为?
好处3:减少迭代时间
使用Unity Addressables会减少在多个过程的等待时间。
我们都体验过按下Unity的Play按钮后,等待约半分钟的时间。如果把构建版本部署到移动平台或WebGL平台,那么情况还会更糟。这种等待时间会大幅增加迭代所花的时间。
任何玩家都不喜欢等待,Addressables系统会提供以下帮助:
减少构建大小
游戏往往有很多内容,玩家喜欢体验内容,而开发者喜欢创作内容,并将把游戏内容提供给玩家。但这并不意味着,我们创作的每个资源都要包含在玩家安装的构建版本中。实际上,我们要尽可能移除不必要的内容。
玩家都希望尽快开始玩游戏。如果游戏需要2GB的数据流量,以及半小时的下载时间,玩家会对此感到不满。这样,玩家可能会更倾向于下载《Candy Crush》这类大小低于50MB的游戏。
其中一种应对策略是:只在安装程序包含主菜单等运行游戏所需的资源,然后在后台下载剩余游戏内容,首先要下载的是游戏的关卡内容。
这也会使开发期间的部署速度变得更快。我们将能够每天迭代更多次数,这个好处会在长期时间中累积效果。
减少加载时间
作为游戏开发者和玩家,我们都讨厌等待。等待会让我们失去玩游戏的状态,我们的游戏时间可能在不经意间就结束了。
Unity正在努力通过改善编辑器和游戏的发布方式,减少玩家开始玩游戏的时间。未来有很多值得期待的功能,例如:Unity 2019.3中避免域重载(domain reloads)的功能很值得期待,但如今它仍处于Beta版。
假设我们正在开发中世纪题材的游戏。数月前,我们为游戏实现了护甲类型。开发过程非常顺利,我们生成了超过100MB的游戏内容。

接下来,我们继续开发其它内容,例如:刀剑对决。我们发现,每次按下Play按钮测试功能时,都会从已开发功能中加载大量数据,而且加载这些数据也需要大量时间。
按下Play按钮测试“刀剑对决”的动画时,由于要加载之前实现的护甲功能,我们会额外等待5秒时间。由于内存带宽有限,因此加载过程耗费的时间大多发生在I/O过程中。此外,CPU也要对该过程进行处理。
作为开发者,我们会在Unity编辑器中耗费相应的时间。而玩家则要在已发布的游戏中等待更多时间。
了解到这个情况带来的影响后,我们要使用什么方法解决该问题呢?
Unity Addressables能够通过两种方法帮助我们。
1
减少玩家的加载时间
我们可以减少玩家的等待时间。使用资源的间接引用而不是直接引用,这样会大幅改善加载时间。
通过使用间接引用,即AssetReference,Unity不会同时加载所有内容,而只在必要时加载部分内容。更重要的是,我们可以直接控制加载内容的时间。
2
减少Unity编辑器上的迭代时间
你对Unity Addressables窗口中的Play Mode Script有多少了解呢?Play Mode Script会定义Unity编辑器如何加载标记Addressable的资源。
选中Packed Play Mode,Unity会直接加载预构建的可寻址资源,仅使用少量处理开销,从而有效减少Unity编辑器中的迭代时间。
使用该功能前,请记得先点击Build Player Content来构建玩家内容。

我们可以试想一下,把这些方法应用到最急需的内容时会产生怎样的效果。
小结
本文,我们了解了Unity Addressables能够帮助进行更好的创作,并给玩家提供更多内容。 我们将从中受益,让项目在未来数月或来年得到提升。
还在用难用的AssetBundle?快来运用Unity新的可寻址资源系统,助力游戏开发的更多相关文章
- 今天我看了一个H5游戏EUI的例子,我都快分不清我到底是在用什么语言编译了代码了,作为刚刚学习H5游戏开发的菜鸟只能默默的收集知识
今天看了一个EUI的demo,也是接触H5游戏开发的第五天了,我想看看我能不能做点什么出来,哎,自己写果然还是有问题的.在看EUI哪一个demo的时候就遇见了一些摇摆不定的问题,我觉得提出来 1.to ...
- 【Unity游戏开发】AssetBundle杂记--AssetBundle的二三事
一.简介 马三在公司大部分时间做的都是游戏业务逻辑和编辑器工具等相关工作,因此对Unity AssetBundle这块的知识点并不是很熟悉,自己也是有打算想了解并熟悉一下AssetBundle,掌握一 ...
- jdk1.8新特性,还不知道的朋友还不看看,1.9都快出来了
一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:代码如下:interface Formula { ...
- 你的 SQL 还在回表查询吗?快给它安排覆盖索引
什么是回表查询 小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键.聚集索引.辅助索引,简单回顾下,聚集索引的叶子节点包含完整的行数据,而非聚集索引的叶子节点存储的是每 ...
- Maven还停留在导jar包?快来探索Nexus私服的新世界
写在前面 Maven,学习框架之前我们都会接触到的一个工具,感觉他的定位,似乎就跟git一样,只是方便我们开发?于是自然而然的,很多小猿对于Maven都只是停留在会用的阶段,利用他来构建,打包,引入j ...
- 还在用em strong吗?快来试试 text-emphasis
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- 【python游戏编程之旅】第九篇---嗷大喵快跑小游戏开发实例
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 前几期博客我们一起学习了,pygame中的冲突检测技术以及一些常用的数据结构. 这次我们来一起做一个简单的酷 ...
- TypeScript 3.3来了!快看看有什么新功能
翻译:疯狂的技术宅原文:https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript 本文首发微信公众号:jingchen ...
- 【Unity游戏开发】SpriteAtlas与AssetBundle最佳食用方案
一.简介 在Unity步入2019.4以后,新版的SpriteAtlas日趋完善,已经完全可以在商业项目中使用了.但是纵观网络平台上,许多关于SpriteAtlas的文章还停留在2018的初版时期,其 ...
随机推荐
- honeydctl命令
# honeydctl Honeyd 1.5c Management Console Copyright (c) 2004 Niels Provos. All rights reserved. See ...
- 【RAC】 RAC For W2K8R2 安装--安装过程中碰到的问题(九)
[RAC] RAC For W2K8R2 安装--安装过程中碰到的问题(九) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也 ...
- php与mysql交互 面向过程
1.建立.关闭与MySQL服务器的连接 1)连接指定的mysql服务器 $mysqli_connect=@mysqli_connect($host, $user, $password,$databas ...
- Web前端之【 iframe 】
iframe基本用法 1.最基本的用法 iframe 标签指定 src <iframe src="demo_iframe_sandbox.htm"></ifram ...
- django的缓存实例应用
那么多的可配置方法,我们用那个呢. 首先在setting中配置你想要的缓存,我这里就用文件的方式是配置.如图: 第二步: 第三步: 第四步: 实现结果: 总结: 都是指明当前资源的有效期,控制浏览器 ...
- 【Mac】微信视频对方听不见你的声音
解决方案: 1.打开系统设置 2.选择声音 3.输出选择第一个就可以
- MySQL/MariaDB数据库的事务和隔离级别
MySQL/MariaDB数据库的事务和隔离级别 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.事务概述 1>.事务Transactions 一组原子性的SQL语句 ...
- Mysql InnoDB行锁不使用索引锁表的时候会锁整张表
原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...
- P2602 [ZJOI2010]数字计数(递推)
P2602 [ZJOI2010]数字计数 思路: 首先考虑含有前导0的情况,可以发现在相同的\(i\)位数中,每个数的出现次数都是相等的.所以我们可以设\(f(i)\)为\(i\)位数每个数的出现次数 ...
- selenium中的等待方法及区别
等待是为了使脚本执行更加稳定 常用的休眠方式: 1.time模块的sleep方法 :引入from time import sleep 2.implicitly_wait():设置webdriver等待 ...