1)Packages 目录下 Shader 打包疑问
2)如何关闭资源的 RW 选项
3)RenderTexture 单个像素的色值大于 Shader 的输出值
4)客户端背包刷新机制
5)PBXProject.AddCapability 添加失败
这是第 218 篇 UWA 技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间 10 分钟,认真读完必有收获。
UWA 问答社区:answer.uwa4d.com
UWA QQ 群 2:793972859(原群已满员)
Q:Unity 引入了 Package Manager 来进行管理插件管理,例如 URP 引入 Packages 之后会有目录 Packages/com.unity.render-pipelines.universal@7.3.1。请教一下各位,如何对 Packages 目录下的资源进行 AssetBundle 打包?
例如,工程目录中有材质球引用到 URP 的 Shader,那么材质球打成 AssetBundle 之后会将 Shader 包含进去,会有 Shader 解析耗时。
A1:我这边是只使用 SBP 而不用 Addressable,这样通过使用 AssetBundleBuild 是可以将 Packages 中的资源也打包成 AssetBundle 的。
将所有依赖到的 Shader(包括 Packages 中的)都使用 AssetBundleBuild 设置到同一个 shader.bundle 的,打包后也解包确认了,Packages 中的 Shader 也打包在 shader.bundle 而不会被包含在材质 AssetBundle 中。
感谢黄晓文@UWA问答社区提供了回答
A2:我在尝试将现有项目转成 URP 的时候,遇到和 Addressable 系统有些不兼容问题。
在打包引用了 URP 的 Shader 的 Material 时会发生 Shader 被重复打包现象。
如果想把 URP 的 Shader 单独打包,又会发现因为不在 Assets 目录内,Addressable 管不到的问题。我的解决方案是将用到的 URP 的 Shader 拷出来,放到 Assets 目录下通用 Shader 目录。
当然需要将该 Shader 改名,并且要注意将内部引用的 Shader 也一并拷出管理。不过一般项目中使用的 Shader 往往还是会自己编写,直接使用官方提供总会遇到这种那种问题。因此我也会考虑尽量不用官方默认 Shader,这时对于 URP 而言自然更加需要将 Shader 拷出来进行改造了。
感谢黄程@UWA问答社区提供了回答
A3:经过 黄晓文 的思路,已经解决。
打包 AssetBundle 最重要的,就是指定资源 Path 的源路径,以及去往的目的 AssetBundle 地址,这个问题关键是需要知道资源在 Packages 中的源路径。例如一个 Packages 下的 Shader 资源,Lit.shader,通过 AssetDatabase.GetAssetPath 可以发现路径是:Packages/com.unity.render-pipelines.universal/Shaders/Lit.shader,这个是正确的路径,用它即可。
而错误的路径分别是:
1.Unity 中看到的:Packages/Universal RP/Shaders/Lit.shader 错误。
2.在文件目录中看到的:Packages/com.unity.render-pipelines.universal@7.3.1/Shaders/Lit.shader 错误。所以得出结论:Packages 下的资源打包,去除一下 @x.y.z 即可。
感谢题主一刀@UWA问答社区提供了回答
A4:可以试试使用 Scriptableobject 或 Material 引用到 Shader 文件,然后把 ScriptableObject 或 Material 打到 AssetBundle 里。
感谢上午八点@UWA问答社区提供了回答
Q:请问一下,一张通过代码创建的 RGBAHalf 图片,然后存储图片资源后缀为.asset,这样运行时图片的 RW 选项是开启的,会导致内存翻倍,大家知道有什么办法能关掉这种资源的 RW 选项么?
A1:动态创建的 Texture 是没法关闭读写的,这里截一下 Texture2D 的一个 isReadable 属性获取的接口说明:
// 摘要:
// Returns true if the Read/Write Enabled checkbox was checked when the texture
// was imported; otherwise returns false. For a dynamic Texture created from script,
// always returns true. For additional information, see TextureImporter.isReadable.
public override bool isReadable { get; }
感谢李星@UWA问答社区提供了回答
A2:解决了,补充一下上面 Profiler 测试的内存是在 PC 上测试的。
其实.asset 图片文件内有个序列化属性为 isReadable 改为 0,在真机上测试运行时 RW 就是关闭的。
感谢题主范世青@UWA问答社区提供了回答
Q:这几天工程在进行粒子特效的性能检测,我们使用了 UWA 的 ParticleEffectProfiler 工具进行性能分析。在进行检测的时候发现一个问题,单个广告板的粒子 Overdraw 为 5,理论上应该是 1 的。我自己断点发现,虽然相机的 Shader 片元输出颜色为 fixed4(0.1, 0.04, 0.02, 0),但是在进行像素绘制次数计算的时候颜色的 g = 0.2196…导致结算结果错误。后来向 UWA 反馈后,技术人员告诉我说把颜色空间改为 Gamma 就好了,试验了一下,确实好了。但是我有困惑。
在线性空间下,Shader 返回的 g 值为 0.04,为什么 RenderTexture 的 g 值为 0.2196…?线性空间下颜色在显示器上显示的不应该是 0.042.2 <0.0016 吗?为什么会是 0.2196…变大的值,难道显示器本身也进行 Gamma 校正吗?再者,Untiy 颜色的线性空间和 Gamma 空间是个什么样的逻辑,怎么感觉跟我学习的知识反着的,亦或者是我理解不到位。请各位大神帮忙解惑。
A1:先简单解释一下,Unity 的 Color Space 为 Linear 时,会在最后输出阶段,进行的伽马校正(Gamma Correction),将 Linear 空间的像素转换为 sRGB 空间。Gamma Correction 会将颜色的亮度变大(补偿),Unity 会将补偿后的像素值输出给显示设备(UWA 的 Effect Scanning 工具会输出到 RenderTexture 上)。
因此,使用 UWA 当前版本的的特效检测功能,应该把项目的 Color Space 设置成 Gamma。如果是 Linear Space,计算得到的 Overdraw 率会偏高。
Gamma Correction( transform the linear values into sRGB) 的公式为:
感谢 Prin@UWA 问答社区提供了回答
Q:网游客户端同步背包数据机制怎么比较合理一点,现在的处理方式是:
1. 登录的时候获取用户背包所有的数据(这个数据量随着游戏运营时间变长,数据量变大)。
2. 服务器差异推送(变化的物品推送)。
3. 从比赛副本出来再全量请求一次全量背包数据,防止差异的包应网络原因没有收到包。
这样的设计方案,实测流量消耗比较大,想优化一下流程,征求各位意见,谢谢。
A1:一般都是这样的,如果是 TCP 根本不需要 3。
感谢 littlesome@UWA 问答社区提供了回答
A2:不知道题主所说的背包数据具体有那些内容,一般背包内存放的都是道具,或者宝箱(其实也是一种道具),碎片(也可以是一种道具)等等。那么这些属性其实基本都是可以序列化到本地文件或者 scriptableObject 的。这个本地文件,或者说对象保存了所有 Item 相关的配置属性。那么网络通信时只需要同步 ID 和数量就行了(根据具体需求可能还有别的,但是应该量很少才对。)
那么假设只是同步 ItemId,ItemCount,通过方法 1 全拉取其实通信量应该不大。
假设 2 个数据都是 int 型,一组 Item 数据是 8 个字节,背包存放 1024 个不同的 Item 才近 8KB。当然也可以压缩一下,int16 能存放 65535 个不同 ID 了,而数量往往会设计的是有上限的,比如:9999,即使超过 65535 个道具,也可以拆分成两个,这样一个 int 的高位可以存放 ID,低位存放数量,1024 个 Item 则是 4k 左右。
序列化后的道具配置表可以做热更下载。往往增加一些新的道具也会涉及到增加新功能,因此一起更新也是必要的。
感谢黄程@UWA问答社区提供了回答
A3:可以考虑利用 ProtoBuf 来同步网络消息,序列化后会被压缩得很小。服务器同步到客户端的时候,也可以利用 GZIP 来压缩,实测压缩率在 1/9 左右。
感谢萧小俊@UWA问答社区提供了回答
A4:建议如下:
1.双端各自维护一个背包数据的版本号,Server 修改背包数据之后就版本号自增 +1。客户端在登录的时候接受来自 Server 的背包版本号,如果发现本地磁盘的版本号和 Server 给的版本号不一样,则请求 Server 进行更新,至于是增量更新/还是全量更新,看具体实现了。
2.差异化推送,也就是增量更新, 这个一般以 key/value 形式推送。
感谢上官狗蛋 er@UWA 问答社区提供了回答
Q:这里返回值都是 true,但是只有第三个 PushNotifications 这个添加成功了(XCode 工程中可以看到),其他的都没添加成功,版本 Unity2019.4.8f1,这是为什么?
proj.AddCapability(target, PBXCapabilityType.SignInWithApple);
proj.AddCapability(target, PBXCapabilityType.InAppPurchase);
proj.AddCapability(target, PBXCapabilityType.PushNotifications);
A:InAppPurchase 需要添加 Storekit 框架,然后加了 Storekit 框架后会自动加上对应 Capability。
感谢吴方杰@UWA问答社区提供了回答
封面图来源于网络
今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在 UWA 问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之 “石”,也能攻你之 “玉”。
官方技术 QQ 群:793972859(原群已满员)