1)抓取手机端变体组合思路构想
2)如何革除File.ReadAllBytes产生的内存泄露
3)atlas.GetSprite(name)内存泄露
4)Unity版本更新后Odin插件序列化报错
这是第303篇UWA技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫10分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)
Shader
Q:对于变体收集的问题,PC端编辑器尽管自带收集,然而毕竟运行的时候是Editor环境,与实在挪动端环境相差甚远。Warmup只会预加载列表中的组合,非Shader打包的全副组合。这样如果收集的变体非实在环境, 只会白白浪费CPU及GPU显存,等实在渲染的时候发现之前提交的组合非挪动端所须要的,须要从新Warmup。
再者,如果做品质划分,比方粗劣画面开动静暗影,晦涩机型关。这样会产生两套组合。实践上应该分成两个SVC,而PC是只能保留所有的变体列表。
综上,我构想解决方案就是通过实在跑手机,抓取手机的应用数据,来划分到不同的列表中,这样应该是最实在牢靠的。
为了实现这个构想,须要能找到如何取得提交的变体数据,已知能够在profiler-CPU-Timeline模式下的Shader.CreateGPUProgram外面的meta_data外面能够拿到。
通过CS源码剖析到NativeProfilerTimeline这个控件是绘制Timeline的外围类。NativeProfilerTimeline.GetEntryInstanceInfo这个函数能够拿到对应的meta_data。
然而这个类是C++底层写的,C#只是Draw去提交绘制。GetEntryAtPosition去依据鼠标地位来取得Entry,代码无奈反射到EntryIndex。当初陷入了死胡同。
大家有解决办法或者新的思路吗?最好能获取手机上的变体列表。
A:能够在Graphics面板上勾选这个Log Shader Compilation:
编辑器下Console连贯真机,这样就能够在触发Shader.CreateGPUProgram时看到相应的Log:
Autoconnected Player Compiled shader: Unlit/TestShader, pass: <unnamed>, stage: all, keywords FOG_EXP2
感激宗卉轩@UWA问答社区提供了答复
Memory
Q:最近我的项目玩的工夫长了,内存始终暴增。在查看过程中,发现游戏中用了一个File.ReadAllBytes办法来读取几个5~10MB不等的二进制数据,加载完数据曾经复制null,然而Mono还是始终增长,调用GC都开释不掉。
实践上来讲这个数组业务层曾经没有援用了。然而,用Memory Profiler查看,内存还始终在。求教一下,有没有人晓得革除的办法?
Unity版本 2019.4.9
A1:缓冲区不必每次都new一个。
感激jim@UWA问答社区提供了答复
A2:如果是Mono版本的APK,能够试试IL2CPP。如果IL2CPP版本没有这个问题,应该是遇到Mono的Bug了,一次性调配较多的堆内存,会概率呈现这些调配的堆内存无奈回收的问题。
感激Xuan@UWA问答社区提供了答复
A3:Boehm GC自身的缺点导致的,能够搜搜BlackList,若有源码,能够有很多种防止或小修的改法;若没源码能够尝试:
- 缩小字典中Struct当Key;
- 拆小文件,重写File的接口,复用内存。
感激kent@UWA问答社区提供了答复
Script
Q:Unity版本 2019.4.23,发现在频繁调用atlas.GetSprite(name) 时会内存泄露,只增不减,直至解体!有人遇到过这问题吗?请问有什么好的解决办法吗?
A1:如果不思考引擎自身Bug的状况下,内存泄露大部分都是援用没有解决好。可能有些中央还在应用这些资源,只是没关联上,导致无奈回收这部分资源。所以能够着重先排查这部分性能。
感激廖武兴@UWA问答社区提供了答复
A2:
//
// 摘要:
// Clone the first Sprite in this atlas that matches the name packed in this atlas
// and return it.
//
// 参数:
// name:
// The name of the Sprite.
public Sprite GetSprite(string name);依据这段的说法是Clone,也就是说每次调用GetSprite,都会执行一次克隆操作,并且不会主动开释。
那么就要用治理脚本做一个缓冲池,反复的Sprite间接从池子里获取。并且开释的时候也从该脚本进行开释。
Dictionary<string, Sprite> mSpritePool = new Dictionary<string, Sprite>();public Sprite GetSprite(string key, SpriteAtlas source) { Sprite result = null; if(!mSpritePool.TryGetValue(key, out result)) { result = source.GetSprite(key); if (result != null) { mSpritePool.Add(key, result); } } return result; }
还能够做SpriteAtlas对象的键值对寄存,不便获取和开释。
感激canyon@UWA问答社区提供了答复
Script
Q:Unity版本更新后Odin序列化,版本更新后,从2020.3.21更新到2021.3.41后就呈现这个问题。
A:Odin仓库有个相似的问题,在3.0.13.0版本修复了,试一下降级插件版本:
https://bitbucket.org/sirenix...
感激羽飞@UWA问答社区提供了答复
封面图来源于网络
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在UWA问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官网技术QQ群:793972859(原群已满员)