1)如何定位游戏发热问题
2)Unity获取指定脚本的援用对象
3)如何晓得打包时的一个Shader有多少变体
4)如何优化Font.CacheFontForText频繁造成的耗时峰值
这是第300篇UWA技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫10分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)
Performance
Q:目前我的项目的发热问题很头疼,2D游戏,基于TileMap、SpriteRenderer和UGUI的渲染,敞开了垂直同步,TargetFrameRate设置为60。Android和iOS上发热都很重大,而且在比拟好的机型(比方iPhone 12这种),发热景象甚至更显著。
跟大部分状况不同,发热并没有怎么影响帧率,在大部分机型上,帧率都不是问题,连iPhone 8机型,都能60帧跑满。
在Unity Profile和Xcode都进行过性能剖析,CPU最显著的热点函数就是Spine的骨骼动画更新计算。然而到一个没有骨骼动画的场景,发热景象稍好点,但还是比预期的要烫不少(场景中除了高空和一些动态贴图,根本就没有多少货色)。
另一个比拟广泛的发热点是网络测试,在某场景敞开网络后,发热仍然重大。甚至启动游戏,停留在登录界面一会儿,发热景象都比别的游戏更显著。
猜想是否因为每帧的顶点数量过多造成的,在游戏中Unity的Status面板,顶点数量Verts达到了40KB,三角形Tris也有简直20KB。看起来很多,但我不太分明以后支流游戏这个数值的级别大略是多少。而且,顶点和三角形的数量很难解释登录界面仍然容易发热,毕竟登录界面这些数值不可能很高。
本人也做了很多测试了,切实搞不清楚问题到底在哪儿,Unity是还有什么特地须要优化的,针对发热的点吗?
A1:能够用Xcode抓帧看看带宽,Load Store Action是否正当。
感激littlesome@UWA问答社区提供了答复
A2:以下是我的倡议:
- iPhone 8上跑满60帧,证实CPU、GPU都没有达到瓶颈,耗费在较为正当的范畴。举荐在Unity Profiler看一下CPU端的耗费,以及查看一下DrawCall数量。
- 举荐应用FrameDebugger,看一下是否有冗余的物体或者后处理在渲染,尤其是你说的启动界面有发热。
- 如果低级谬误都排查过了,那么倡议看一下是否用了原生的插件。
- 渲染的分辨率是否调整过了,RenderScale的值和FrameDebugger能够查出来分辨率。
感激张振东@UWA问答社区提供了答复
A3:对于发热的问题,通常要从几个角度排查:CPU压力(耗时)、GPU压力(耗时和带宽,能够思考升高分辨率看看发热问题是否会有改善)和IO等几个角度。从题主的问题上看,耗时应该是没问题,都能跑满帧(当然60帧自身就是对发热影响比拟大的一点,能够看看限度30帧会不会发热有降落),所以要看看一些隐形的货色是否有问题。比方带宽,能够用Snapdragon在高通手机上跑一跑。如果带宽较高,看看纹理的一些设置是否正当,比方是否压缩、是否开启Mipmap,这两项通常都是须要设置成开启的。还能够查看是否有不必要的BlitCopy操作,在URP我的项目中比拟容易呈现Copy Color和Copy Depth节约。对于IO,须要看看是否存在子线程外面有频繁IO的景象。
感激Xuan@UWA问答社区提供了回
Script
Q:Unity获取指定脚本的援用对象:一个GameObject上挂载了一个Script,这个Script援用了很多资源。如何只取得这个Script援用的资源呢?AssetDatabase是会获取所有的援用,然而并没有做辨别。
A1:有Guid能够应用以下代码加载:
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var texture2D = AssetDatabase.LoadAssetAtPath(assetPath);
感激萧小俊@UWA问答社区提供了答复
A2:通过SerializedObject拿到了所有的ObjectReference,而后AssetDatabase.GetAssetPath获取对应门路:
var assetObj = AssetDatabase.LoadAssetAtPath<Object>(path);if (assetObj != null){ GameObject gameObj = assetObj as GameObject; if (gameObj != null) { MeshRendererTextureStreamingData streamingOBJ = gameObj.GetComponent<“taget component”>(); if (streamingOBJ != null) { SerializedObject so = new SerializedObject(streamingOBJ); SerializedProperty it = so.GetIterator(); bool first = true; while (it.Next(true)) { if (it.propertyType == SerializedPropertyType.ObjectReference && it.objectReferenceValue!=null) { // Debug.LogError(it.objectReferenceValue); var depPath = AssetDatabase.GetAssetPath(it.objectReferenceValue); streamingAssets.Add(depPath); } } } }}
感激题主null@UWA问答社区提供了答复
Shader
Q:有什么办法能够晓得打包的时候的一个Shader有多少变体?
A:间接应用Unity提供的回调函数,该函数会在Shader被打包(无论是打AssetBundle包还是Build的时候)时主动调用。
如图的三个参数:“shader”示意回调函数以后在解决的Shader资源,”data”是参加编译的变体列表。所以data.count()就是该Shader资源的(参加编译的)变体数量了。所以,只有在回调函数逻辑里把这两个参数Log输入就行了。
感激Faust@UWA问答社区提供了答复
UGUI
Q:请问 Font.CacheFontForText频繁造成耗时峰值,该如何优化?
A:能够参考这篇文章:《Unity3D UGUI 优化:Font.CacheFontForText》
Font.CacheFontForText是在Text渲染时,当对应字体的FontTexture找不到须要渲染的字符时,就会从新生成FontTexture,FontTexture尺寸越大,从新生成这张FontTexture就越耗时。
因而为了缩小运行过程中该函数造成的耗时峰值,能够当时渲染所须要的字符,防止在运行时呈现从新生成FontTexture。
应用UWA的GOT Online工具验证了一下下面所提到的解决方案,后果比照如下所示:
优化前
优化后优化后之所以还是存在局部Font.CacheFontForText的耗时峰值,是因为在测试前期又渲染了之前FontTexture中没有的字符。
感激宗卉轩@UWA问答社区提供了答复
封面图来源于网络
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在UWA问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官网技术QQ群:793972859(原群已满员)