1)应用 Streaming Mipmap 后纹理内存没有降落的疑难
2)TCP 网络传输大端 / 小端疑难
3)Texture Compression,Default 和 Override 有什么关系
4)如何疾速革除 Log
这是第 299 篇 UWA 技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫 10 分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ 群 2:793972859(原群已满员)
Texture
Q:为什么我在我的项目中应用了 Streaming Mipmap 然而在 GOT 报告中看纹理内存没有降落?是没有正确失效还是统计有问题?
A:之前做过相干测试,发现 GOT Online 是能够统计到被 Streaming Mipmap 影响的纹理的正确内存的,所以我揣测你遇到的状况大概率还是没有正确失效导致的。以下是对如何让一张纹理利用 Streaming Mipmap 的简略流程总结,其中会注明须要特地留神的一些条件(有些被官网文档收录,有些则文档中没有,但试验证实为必要):
- 在 Project Settings-Quality 中开启 Texture Streaming 选项。然而试验发现 Editor 中开启该选项而真机上却会生效的景象,导致所有纹理的 Streaming Mipmap 设置全副生效。所以为了确保失效,首先应该在代码中调用 QualitySettings.streamingMipmapsActive API 全局地开启这个选项,能力确保 Streaming Mipmap 可用。
- 调整 1 中设置的参数。比拟重要的参数是 Memory Budget 参数和 Max Level Reduction 参数。Memory Budget 示意纹理资源的估算,默认值是 512MB,但依据 UWA 的大量我的项目数据来看,中低端机上个别为 200MB 左右。它的数值代表的是所有纹理资源的估算——即,它既包含了非流式的纹理、又包含了咱们想要采纳流式的纹理——但这个“估算”并不代表纹理资源可占用的下限,只是 Unity 判断对于一个开启 Streaming Mipmap 的纹理到底采纳它的哪些 Mipmap 通道的参考值,非流式纹理可能轻易冲破这个估算。
Max Level Reduction 则是代表着 Unity 通过流式存储最高能取到哪一级的 Mipmap 通道,这个参数的优先级比 Memory Budget 要高,也就会造成理论内存超过预算的状况。(比方该参数为 2 时,则最多剔除 Mipmap0 和 1 通道,即使抛弃当前还远超出预算值也不会进一步剔除。)
也就是说,如果 Memory Budget 值设置的远高于我的项目中纹理理论占用的内存,则 Texture Streaming 可能齐全不起效,所有开启 Streaming Mipmap 的纹理仍将保留它们的全副 Mipmap 通道。
设置开启 Streaming Mipmap 的纹理。1、2 中提到的设置只对开启了 Streaming Mipmap 的纹理起效,而这只是官网文档的说法,从实际操作来看,Texture Streaming 只对同时满足以下三个条件的纹理失效:
1)开启了 Streaming Mipmap 且开启了 Generate Mipmap 的纹理(这一点官网文档中没有提及,事实上开启 Generate Mipmap 才会生成 Mipmap 通道供 Streaming Mipmap 剔除);
2)被即时加载的纹理(如一开始就曾经在场景中被依赖的纹理,即使开启了 Streaming Mipmap 其内存也不会发生变化,通过 AssetBundle 加载和 Res.Load() 加载的纹理则能够),也即官网文档中这句话的理论含意:
如果是进行 Android 开发,还须要关上 Build Setting,并将 Compression Method 设置为 LZ4 或 LZ4HC。Unity 须要应用其中一种压缩办法进行异步纹理加载,这是纹理串流零碎所必须的操作。
3)Gfx 局部内存(这里指的是纹理资源开启 Read/Write 选项时,复制到 CPU 端的那一部分内存是不受 Streaming Mipmap 影响的);
- Streaming Mipmap 剔除 Mipmap 通道的法则。它的机制其实和 Texture Quality 是相似的。咱们晓得,开启 Mipmap 的纹理之所以会变成原来的 4 / 3 倍,实际上是它各个通道所占用的内存之和。举例而言,一个具备 11 个 Mipmap 通道的原大小为 1MB 的纹理(10241024 分辨率、ASTC44 格局),其内存占用为 1 +1/4+1/16+…的 11 项等比数列之和,即约 4 /3。等比数列的各项就对应了 Mipmap0、Mipmap1、Mipmap2…等各个 Mipmap 通道。那么,当 Max Level Reduction 参数设置为 2 时,其实际意义就是保留 Mipmap2 和后续所有更小的通道,而剔除 Mipmap0 和 Mipmap1 通道,此时的内存大小为 4 /3MB-1MB-1/4MB=85.33KB。这和我在 Profiler 或 GOT Online 中看到的数据基本一致。
- 对于采纳 Streaming Mipmap 计划的倡议。根据上述试验和剖析不难看出,Streaming Mipmap 是的确具备一些长处的,对于对内存比拟敏感,尤其是纹理内存占用很大的我的项目,采纳 Streaming Mipmap 计划是十分正当和举荐的选项。与此同时,它的理论应用要求对我的项目中纹理资源的内存占用有相当的理解和布局——相干设置在 Quality 中,天经地义地应该思考到不同设施 Lod 分级时不同的设置。在中低端机中,设置尽量低的 Memory Budget 和尽量高的 Max Level Reduction;在高端机上则恰恰相反,在内存可承受范畴内尽量开启最好的画面体现。除此之外,对于哪些纹理要开启 Streaming Mipmap,个别是场景中 3D 物体的纹理,而 UI 模块采纳的纹理则尽量敞开。因为 Mipmap 的意义次要在于适应纹理在间隔镜头远近时的体现须要、防止失真等,而 UI 齐全不须要这些,开启只会白白浪费内存和计算工夫。
感激 Faust@UWA 问答社区提供了答复
Network
Q:网络协议规定对立应用大端数据传输,然而测试用小端数据发送,而后服务器收到间接返回给客户端,客户端能够正确解析。所以就有个疑难:数据传输不须要大小端转换?还是底层帮忙转了?
测试例子如下:音讯头部固定 4 个字节,值为 body 的长度。服务器没做任何解决收到音讯间接返回。客户端收到音讯先解析头部长度 4 个字节,拿到 body 长度再获取 body 具体数据。没有大小端转换然而解析都正确:
{
// 测试发送整数
var bodyMsg = "测试发送数据";
var bodyBytes = Encoding.UTF8.GetBytes(bodyMsg);
// 发送头部长度,固定 4 个字节
int headLen = bodyBytes.Length;
var headBytes = BitConverter.GetBytes(headLen);
// 发送头部长度音讯
_sendSocketAsyncEventArgs.SetBuffer(headBytes, 0, 4);
_socket.SendAsync(_sendSocketAsyncEventArgs);
// 发送 body 音讯
_sendSocketAsyncEventArgs.SetBuffer(bodyBytes, 0, bodyBytes.Length);
_socket.SendAsync(_sendSocketAsyncEventArgs);
}
A:测试发送的数据只有在多字节数据处理时才须要思考字节序,如果是 Protobuf,是不必思考字节序的。
底层不会主动进行大小端转换,须要写代码,所以个别都是我的项目初期就约定好。<br/>
另外,如果把服务器放到不同物理机则测试后果就是错掉的,正确做法是得把发送数据转为大端,比方下面音讯头要加上 if (BitConverter.IsLittleEndian) {Array.Reverse(headBytes); },而后在收到数据后再转为小端。
感激萧小俊 @UWA 问答社区提供了答复
Texture
Q:请问纹理的格局设置项,BuildSettings 外面 Texture Compression,Default 和 Override,这几个是什么关系?
A:纹理设置中 Override For Android 这一项的优先级最高;不勾选 Override 的状况下是 Default 中的格局。如果既没有勾选 Override,也没有扭转 Default 标签下的格局设置,并且批改了 Texture Compression 选项,才会采纳 Texture Compression 的格局设置,并且也只对合乎上述条件的纹理失效。
感激宗卉轩 @UWA 问答社区提供了答复
Script
Q:咱们我的项目开发过程中应用 Log 还是比拟多的,测试的时候发现对性能影响比拟大、所以想在下版本中排除掉 Log 再看看性能数据。有没有比手动正文 Log 更好的办法?另外 Release 版本还会有 Log 吗?
A1:能够本人封装一个 Log 函数,Log 函数外部再代用 Debug.Log。能够在 Void 上加上 [Conditional(“DEVELOPMENT_BUILD”),Conditional(“UNITY_EDITOR”)],这样只有 Debug 版本和 Editor 才会调用。
感激萧小俊 @UWA 问答社区提供了答复
A2:补充一下,较新版的 Unity 中提供了接口 Debug.unityLogger.logEnabled = false,放在打 Log 的逻辑之前就能防止所有 Debug 类触发的所有 Log 了。另外 Release 版本是无奈革除 Debug.Log 的,还是要尝试用楼上或者 API 的形式去革除。
感激 Faust@UWA 问答社区提供了答复
封面图来源于网络
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在 UWA 问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA 学堂:edu.uwa4d.com
官网技术 QQ 群:793972859(原群已满员)