6

使用ScriptableObject代替部分配置表的坑点

 3 years ago
source link: https://blog.uwa4d.com/archives/TechSharing_231.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1)使用ScriptableObject代替部分配置表的坑点
​2)加载配置内存过大问题
3)URP的UI在Android模型器下比在真机上暗
4)Unity在Windows上第一次运行Play启动很慢
5)如何正确卸载UnityWebRequest下载的图片资源


这是第231篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Script

Q:ScriptableObject可以通过Runtime修改,资源可以拖拽配置。这些都是Excel无法做到的优势。

所以准备尝试用ScriptableObject代替部分Excel的配置用在项目里。想知道,ScriptableObject这样用,大家有没有遇到过比较严重的坑点?例如这样的Asset的加载、解析的空间或时间上的开销是否可接受等等。

补充一下,比如装备是成组的,对每组装备做一个ScriptableObject对应的Asset拖一组装备Prefab引用,然后由外部持有ScriptableObject Asset的路径即可。像这种部分资源相关的配置走这套,粒度更细,一个Asset中包含的资源本身就是应该被同时加载的。这种情况是不是没有这种冗余加载的问题?

A1:之前的项目曾经用过这种方式做配置表,但是随着表格和配置的增加,会出现许多问题,比如以下几个:

  1. 内存:内存要比普通的加载、解析二进制文件要大不少,大概有8倍。
  2. 加载速度:加载速度比普通的解析二进制要慢十倍以上,也是个大概值,毕竟是三年前做的项目了。
  3. 卡顿:ScriptableObject的加载和解析都在主线程,会卡主线程,而自己实现的二进制可以自己写个子线程去解析,就算在主线程解析起来也很快。这块大概也是十倍的量级。
  4. 硬盘:如果二进制不压缩,其实硬盘上差距不那么大,但是稍微用zip压缩一下,就有十倍的差距了。
  5. 策划:如果面对大量的数据,Excel显然更能帮助策划高效地配置,比如现在需要配置100个道具,如果用ScriptableObject比较复杂。
  6. Runtime:Runtime修改虽然做不到,但是热重载是可以做到的,效率也不差多少。
  7. 资源可拖拽:这个功能你调查过策划是否喜欢了吗?
  8. 热更新:如果项目使用的语言是Lua,ScriptableObject会阻碍新增字段的更新,毕竟是C#声明的字段(或者后续有表格热更新增字段、表格的需求)。

以上情况如果都能接受,那么用ScriptableObject是可以的。据我所知,还是有一些上线项目是用这套方案的,并且也稳定运营了3年以上。

感谢xiaobai@UWA问答社区提供了回答

A2:举个例子,比如一个装备表关联上百个装备模型。加载直接拖上去的ScriptableObject就得同时加载这上百个装备模型。如果不用拖拽引用,这个的可编辑性远远不如Excel。

感谢欧月松@UWA问答社区提供了回答

A3:一般这种资源引用,可以考虑使用一个可加载的路径或者地址来代替,避免直接引用带来的同时加载问题。

感谢静风霁@UWA问答社区提供了回答

A4:ScriptableObject大部分时候还是没有Excel好用的,比如在公式和索引上,也无法快速定位配置错误,但是大多数Editor的编辑器功能需要用到ScriptableObject。

我们项目的方案是Excel转Protobuf + ScriptableObject转Protobuf,运行时只加载Protobuf的二进制文件即可。

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fcd9c0710a17c6c2b09d559


Script

Q:配置表太多占用内存过大时,除了采用Sqlite,还有什么好的解决办法吗?FlatBuffer不用全部进内存吗?如果不全部进内存,访问速度如何呢?

A1:解答第一个问题:

  1. 可以针对重复数据进行剔除,尤其是一些字符串的配置。在配置导出时把这样的数据提取一份,其他用到的地方只是引用,会节省不少。
  2. 数据类型要合理。
  3. 可以使用类似FlatBuffer/ZeroFormatter的延迟加载的思路,在真正使用时再去反序列化。一次游戏过程中实际用到的配置量比较有限,使用这种策略可以尽可能地减少不必要数据的加载(这一条可能主要适用于C#层去读配置的,如果你们是存成Lua这条就不一定适用了)。

解答第二个问题:
我们上个项目也是到后期优化时遇到类似问题,只是参考了这种思路,并没有进行完全替换。在打包时,会对配置以行为单位,进行Offset和Length的计算;在Runtime阶段,初始加载只会加载每行的ID,对应的这一行的Offset和Length,然后后续逻辑调用配置表接口拿数据的时候,如果发现没有反序列化过,就根据Offset和Length再去构建一下相应的数据提供给上层。访问速度肯定没有开始直接全部加载的好,但我们测下来影响不大。

感谢范君@UWA问答社区提供了回答

A2:字符串吃内存,尽量少用或者复用。
表格中比较多的会是哪种?攻击-1000、防御-2000、血量-3000,每个Int都是4个字节,数量多了会顶不住。这种可以考虑用一个int32/int64/uint32/uint64去存多个数值。

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fc8254010a17c6c2b09d48c


Rendering

Q:URP的UI在很多Android模型器下的明显比在手机上要暗很多。确认模拟器用的Gles3.0+ 支持Linear色彩空间,看上去就像是模拟器对UI进行了一次额外的GammaToLinearSpace,如果在导入UI图片时把sRGB勾掉,或者进行一次LinearToGamma,就能在模拟器上显示正常,但手机上就颜色太亮了,如下图:

1.png

A1:最新进展:之前用2019.3.5f1,更新到2019.4.10f1就没有这个问题了。

感谢题主loy_liu@UWA问答社区提供了回答

A2:Unity论坛有很多人反馈SRP + OPENGL ES + Linear Color Space在Android上面有渲染Bug。

看下Player Settings->Android->Resolution and Presentation->Blit Type设置成Auto能否解决问题呢?

感谢范君@UWA问答社区提供了回答

A3:2019.3.6f1的Release Note里有说到这个是Bug。

Mobile: [Android] [Gles3] [URP] Darker UI when using Gles3, Linear and URP

感谢Xuan@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fbf460e10a17c6c2b09d375


Editor

Q:Unity在Windows上第一次运行Play启动很慢,但在Mac上没有这个问题。该如何进行排查呢?

A1:Mac没问题,有可能是Play启动游戏的时候在扫描各种资源文件导致,可以排查下AssetPostprocessor相关的,比如OnPostprocessAllAssets是不是每次启动的时候都在遍历。

感谢Kenji@UWA问答社区提供了回答

A2:如果是Editor的问题可以试一下Unity官方提供的编辑器耗时分析工具Performance Tracking(2019.4+),低版本从Profiler中看看能不能定位到耗时。

Performance Tracking
ScriptableObject导致的类似的问题

感谢羽飞@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fd0640910a17c6c2b09d5bb


Resource

Q:通过UnityWebRequest和DownloadHandlerTexture下载的Texture资源,下载完成后赋值到RawImage组件,如何正确卸载UnityWebRequest下载的图片资源?

A:我们上个项目此类Texture都会被专门的Manager管理起来,确保没有被其他GameObject引用后,使用Object.DestroyImmediate来销毁掉,虽然这个接口官方不推荐使用。

或者可以尝试下确保没有引用后使用Object.Destroy卸载或等待下次调用Resources.UnloadUnusedAssets时来卸载。

感谢范君@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fd2129410a17c6c2b09d60c

封面图来自网络


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK