C#初中级实战—3DFlipBird(四)缓存池与性能分析(UPR+夜神模拟器)

编程入门 行业动态 更新时间:2024-10-15 00:25:36

C#初中级实战—3DFlipBird(四)缓存池与性能分析(UPR+夜神<a href=https://www.elefans.com/category/jswz/34/1769563.html style=模拟器)"/>

C#初中级实战—3DFlipBird(四)缓存池与性能分析(UPR+夜神模拟器)

文章目录

  • 缓存池概念:
  • 制作方法:
  • 效果:
  • 性能测试:
    • URP添加测试
  • 结果分析:
    • 标准手机打包(中质量)
      • 缓存池
      • 无缓存池
    • 最高质量打包
      • 缓存池
      • 无缓存池

缓存池概念:

缓存池,关键在于缓存二字,如何缓存呢,即保存到某个地方,每次需要创造某个物体时先从缓存池里看看有没有,有就从缓存池里拿出来用,不进行创造。用完了就放到缓存池里面、

制作方法:

我们每次创建障碍物应该先从缓存池里面找有没有障碍物,有的话就直接从缓存池里面拿出来,又因为我们有很多不同的障碍物,所以我们使用字典,查找对应缓存池是否存在,没有就创建一个,有就放进去。
缓存池字典

public Dictionary<string, PoolDate> poolDic = new Dictionary<string, PoolDate>();

缓存池类:我们找一个父物体,将池子里的东西都放到对应的池子下面


public class PoolDate
{public GameObject fatherObj;//缓存对象的父节点public List<GameObject> poolList;//对象的容器public PoolDate(GameObject obj, GameObject poolObj){//给缓存池创造一个父对象,并且将其作为总pool的子物体fatherObj = new GameObject(obj.name);fatherObj.transform.parent = poolObj.transform;poolList = new List<GameObject>() { };PushObj(obj);//创建池子时将第一个物体放进去}/// <summary>/// 存物体/// </summary>/// <param name="obj"></param>public void PushObj(GameObject obj){obj.SetActive(false);//失活,隐藏//存起来poolList.Add(obj);//设置父对象obj.transform.parent = fatherObj.transform;}/// <summary>/// 取物体/// </summary>/// <param name="name"></param>/// <param name="transform"></param>/// <returns></returns>public GameObject GetObj(){GameObject obj = null;obj = poolList[0];poolList.RemoveAt(0);obj.SetActive(true);//激活显示obj.transform.parent = null;//断开父子关系return obj;}
}

写一个创造方法 替代之前的Instantiate方法

我们将物体名字传进去,并且将要创造的物体和位置传进去(如果没有池子,就根据这个创建物体)
传名字是为了给物体改名(一个物体第一次肯定不在池子里,且名字会带clone,目的就是改掉clone,方便存储和取出)

 public GameObject GetObj(string name,GameObject gameObject,Transform transform){ //有池子,有东西if (poolDic.ContainsKey(name) && poolDic[name].poolList.Count > 0){return (poolDic[name].GetObj());}else{Debug.Log("物体的名字"+name);Debug.Log("物体/池子不存在");var reNameObj = GameObject.Instantiate(gameObject, transform);//Debug.Log("实例化的物体的名字" + reNameObj.name);reNameObj.name = name;return null;}}

我们在物体出现一定时间后,不是将物体销毁而是放到对应的池子里。用Push方法替代Destroy方法。
在ObstacleBase脚本里,创建Push方法,传物体自己的名字和自己


在PoolManager中定义存的方法,判断池子和其中是否有物体,存到对应名字的池子里,并且隐藏物体。(拿出来的时候激活物体)

public void PushObj(string name, GameObject obj){//里面有池子if (poolObj == null){poolObj = new GameObject("pool");}obj.SetActive(false);//失活,隐藏obj.transform.parent = poolObj.transform;//设置父对象if (poolDic.ContainsKey(name)){poolDic[name].PushObj(obj);}else//里面没有,加入一个{poolDic.Add(name, new PoolDate(obj, poolObj));}}

效果:



可以看到 Hierarchy窗口出现Pool,里面是不同障碍物对应的池子,每当物体定时时间到了,就会进入缓存池,而另一边创造物体 会优先从缓存池拿物体,当物体不够再进行创造
最后在游戏结束(血量清零)清除缓存池(否则重新开始游戏可能会出现问题),每次开始游戏也可进行缓存池的清除。

性能测试:

下面进行性能测试,这里用UPR+夜神模拟器进行测评
目前UPR已经不支持直接在编辑器模式下测试了,要么打包测,要么profiler

测评方法:
下载upr windows,下载upr package 加载进项目里面


项目打包
下载夜神模拟器

URP添加测试

开启模拟器同时开启UPR windows,在urp官网登录-我的项目-创建项目-新建测试

这里测试4次,两次中质量打包,两次最高质量打包(增加模拟器的渲染压力),其中2次使用缓存池,2次不使用缓存池

将建立好的测试复制Session id到 Windows中,然后选择ADB。此时模拟器应该是打开状态且安装了对应的app,点击之后Start,就开始测试了,测试完点击Stop即可完成测试(官网有视频教程)

结果分析:

标准手机打包(中质量)

先看标准手机打包(中质量)下,缓存池对于性能的影响

缓存池


无缓存池



可以看到,缓存池对于性能影响不高,GC的次数居然还多了(可能是测试时间不一样长),GC的峰值时间变长了,帧数基本变化不大,不过使用了缓存池的CPU运行比较平稳,帧数更加稳定。

最高质量打包

下面看如果渲染压力比较高的情况下,缓存池是否会有效果:

缓存池


内存占用

GC

无缓存池


内存占用

GC

可以看到,在高渲染压力情况下,帧数直接掉一半,使用了缓存池的帧数还略低一点,内存情况是,使用了缓存池的内存确实用的更多,而且峰值GC时间和 普通画质下的情况一样,都 比不使用缓存池要高。还有一点情况和普通画质一样的是,使用了缓存池的CPU运行时间比不使用缓存池平稳运行时间更长(毛刺更少),说明帧数更稳定。
不过使用了缓存池的GC数量却比不使用更多,这一点比较困惑,也许需要更多测试样本。
对于此项目来说,画质的优化是重头,cpu优化反而不那么重要,两次画质的不同直接导致帧数掉了一半,所以如果要优化,应该往模型面数,贴图尺寸等画面表现来进行(粒子,shader之类的),应该看一下相关参数,不过此次重点是GC对于性能的影响,别的指标就下次再讨论了。(UPR之初体验)

更多推荐

C#初中级实战—3DFlipBird(四)缓存池与性能分析(UPR+夜神模拟器)

本文发布于:2024-03-06 05:32:05,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1714489.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模拟器   缓存   实战   初中   性能

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!