Packages目录下Shader打包疑问

Packages目录下Shader打包疑问

1)Packages目录下Shader打包疑问
​2)如何关闭资源的RW选项
3)RenderTexture单个像素的色值大于Shader的输出值
4)客户端背包刷新机制
5)PBXProject.AddCapability添加失败


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

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

AssetBundle

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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5f3d10b19424416784ef1c82


Texture

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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5f50f0439424416784ef20c4


Rendering

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.04^2.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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5f51b8ba9424416784ef20d7


Script

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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5f4657969424416784ef1f65


Build

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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5f4719169424416784ef1fbc

封面图来源于网络


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

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com

官方技术QQ群:793972859(原群已满员)