关于performance:如何定位游戏发热问题

39次阅读

共计 3283 个字符,预计需要花费 9 分钟才能阅读完成。

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:以下是我的倡议:

  1. iPhone 8 上跑满 60 帧,证实 CPU、GPU 都没有达到瓶颈,耗费在较为正当的范畴。举荐在 Unity Profiler 看一下 CPU 端的耗费,以及查看一下 DrawCall 数量。
  2. 举荐应用 FrameDebugger,看一下是否有冗余的物体或者后处理在渲染,尤其是你说的启动界面有发热。
  3. 如果低级谬误都排查过了,那么倡议看一下是否用了原生的插件。
  4. 渲染的分辨率是否调整过了,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(原群已满员)

正文完
 0