目录
2.导入后,找到文件夹Black Leaf里的Preform文件夹,将FPSCanvas预制体拉进场景内即可使用。
一、效果图
1.功能介绍:
- 适用于PC端、WebGL、编辑器。
- 左上角面板有场景面数点数(若模型没开启计算则有误差)、自动化日期(打包后固定未打包当天日期)、项目名字。
- 左边面板有当前屏幕分辨率大小,所支持最大帧率及设备信息。
- 右边面板有帧率和其他性能消耗信息。
- 游戏运行就可执行,也可取消勾选游戏开始运行,按p键可隐藏和开启。
2.相关参数说明:
- 帧率: 帧率是用于测量显示帧数的量度。测量单位为“每秒显示帧数”(Frame per Second,FPS)或赫兹,一般来说FPS用于描述视频、电子绘图或游戏每秒播放多少帧”,通俗点说,帧率就是每秒播放了多少页的画面。帧率越高,玩游戏的体验就越好。
- 堆内存:返回托管内存的预留空间大小。 当分配的托管内存总量超过当前的预留数量时,此值将增加。 托管分配的预留空间大小也会影响垃圾回收器的运行频率,以及收集垃圾所需的时间。堆越大,所需的时间越长,但运行的频率越低。
- 使用大小:获取活动对象和非收集对象的已分配托管内存。 该函数返回为所有对象分配的托管内存量,包括活动对象和非收集对象。总是调用GC。在调用此函数之前收集,因为未引用的对象在垃圾收集器(GC)收集它们之前仍然占用空间。这将返回一个不断增加的值,直到GC。调用Collect。分析器的大小。GetMonoHeapSizeLong可能会在后续GC之后减少。如果是第一个GC,则调用Collect。Collect调用收集堆部分中所有剩余的对象。分配新的内存也可能隐式地重新触发GC。收集,如果它发现自第一次调用以来准备收集的对象更多, 它可能会降低Profiler的值。GetMonoUsedSizeLong返回更多。此外,Unity可能会在线程上分配托管内存,或者线程代码可能会删除指向托管分配的指针,所以虽然看起来没有代码应该改变两个度量点之间的托管分配量,但事实并非如此。
- unity分配:Unity 中的内部分配器分配的内存总量。Unity 在系统中预留了大型内存池。此函数将返回这些池中使用的内存量。
- 总内存:Unity 预留的总内存。 此函数返回 Unity 为当前和未来分配预留的内存总量。如果预留内存已用尽,Unity 会根据需要从系统中分配更多内存。
- 未使用内存:当 Unity 需要分配内存时,Unity 会在池中分配内存以供使用。此函数返回这些池中未使用的内存量。
3.问:降低内存使用的最佳实践是什么?
答:概括例如以下:
- 降低Unity堆的大小
- 尽可能保持“WebGL Memory Size”足够小
- 降低代码量
- 启用Strip Engine Code
- 禁用异常检測
- 避免使用第三方插件
- 降低数据大小
- 使用Asset Bundles
- 使用Crunch纹理压缩
二、使用步骤
1.导入package包
资源链接如下:
【免费】Unity-参数画布.unitypackage资源-CSDN文库
2.导入后,找到文件夹Black Leaf里的Preform文件夹,将FPSCanvas预制体拉进场景内即可使用。
3.在LoadGameManager下可以进行相关操作。
(1)DIsplay:勾选即游戏游戏就执行
(2)Project Name:打包后项目名字也显示在参数画布上
4.部分代码演示
using System;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.UI;
public class DlgFramesList : MonoBehaviour
{
public bool display;
public int targetFrameRate = 500;
public GameObject showPanel;
public Text showFpsText;
public Text heapSizeText; //堆内存
public Text usedSizeText; //使用的
public Text allocatedMemoryText;// unity分配
public Text reservedMemoryText; // 总内存
public Text unusedReservedMemoryText; // 未使用内存
//public Text RuntimeMemorySizeLong; // 收集 Unity 对象使用的本机内存
private float fpsByDeltatime = 1.5f;
private float passedTime = 0;
private float frameCount = 0;
private float realtimeFPS = 0;
private int _index = 1;
private int _indexCount = 100;
private TimeSpan _preCpuTime;
private TimeSpan _curCpuTime;
private const float Mb = 1024f * 1024f;
private int verts;
private int tris;
public Text vertsTrisText;
public string projectName="Shop";
private void Start()
{
if (showPanel.activeSelf != display)
showPanel.SetActive(display);
_preCpuTime = _curCpuTime;
SetFps();//设置FPS
GetAllObjects();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
display = !display;
showPanel.SetActive(display);
if (display)
ShowProfilerMsg();
}
GetFps();//获取实时FPS
if (display)
{
_index++;
if (_index == _indexCount)
{
ShowProfilerMsg();
}
}
}
#region 获取点&面数
void GetAllObjects()
{
verts = 0;
tris = 0;
GameObject[] ob = FindObjectsOfType(typeof(GameObject)) as GameObject[];
foreach (GameObject obj in ob)
{
GetAllVertsAndTris(obj);
}
}
//得到三角面和顶点数
void GetAllVertsAndTris(GameObject obj)
{
Component[] filters;
filters = obj.GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter f in filters)
{
if (f.sharedMesh.isReadable == false)
{
Debug.Log(f.sharedMesh.name + "未开启'read/write'+面数&顶点数不计入");
continue;
}
tris += f.sharedMesh.triangles.Length / 3;
verts += f.sharedMesh.vertexCount;
}
Component[] MSRs = obj.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer item in MSRs)
{
if (item.sharedMesh.isReadable == false)
{
Debug.Log(item.sharedMesh.name + "未开启'read/write'+面数&顶点数不计入");
continue;
}
tris += item.sharedMesh.triangles.Length / 3;
verts += item.sharedMesh.vertexCount;
}
DateTime buildDate = DateTime.Now;
vertsTrisText.text = tris.ToString("Tris-当前场景所有面数 #,##0") + "\n" + verts.ToString("Verts-当前场景所有顶点数 #,##0")+ "\n"+
"Build Date: " + buildDate.ToString("yyyy-MM-dd") + "\n" + projectName;
// vertsTrisText.text = tris.ToString("Tris-当前场景所有面数 #,##0") + "\n" + verts.ToString("Verts-当前场景所有顶点数 #,##0");
}
#endregion
private void ShowProfilerMsg()
{
_index = 0;
//堆内存
if (heapSizeText)
{
heapSizeText.text = "堆内存: " + Profiler.GetMonoHeapSizeLong() / Mb + " Mb";//减小Unity Heap的大小:
}
//使用的
if (usedSizeText)
{
usedSizeText.text = "使用大小: " + Profiler.GetMonoUsedSizeLong() / Mb + " Mb";
}
// unity分配
if (allocatedMemoryText)
{
allocatedMemoryText.text = "Unity分配: " + Profiler.GetTotalAllocatedMemoryLong() / Mb + " Mb";
}
// 总内存
if (reservedMemoryText)
{
reservedMemoryText.text = "总内存: " + Profiler.GetTotalReservedMemoryLong() / Mb + " Mb";
}
// 未使用内存
if (unusedReservedMemoryText)
{
unusedReservedMemoryText.text = "未使用内存: " + Profiler.GetTotalUnusedReservedMemoryLong() / Mb + " Mb";
}
}
private void ShowCpuMsg()
{
// 间隔时间(毫秒)
int interval = 1000;
var value = (_curCpuTime - _preCpuTime).TotalMilliseconds / interval / Environment.ProcessorCount * 100;
_preCpuTime = _curCpuTime;
}
private void SetFps()
{
Application.targetFrameRate = 500;
}
private void GetFps()
{
/*帧数和时间增加*/
frameCount++;
passedTime += Time.deltaTime;
//满足1.5,则计算并更新显示一次FPS,在恢复计数
if (passedTime > fpsByDeltatime)
{
realtimeFPS = frameCount / passedTime;
showFpsText.text = "FPS(帧率):" + realtimeFPS;
}
}
}
5.运行效果
1.编辑器运行效果
2.PC端运行效果
3.WebGL端运行效果
(略)
总结
以上就是我做的一个unity小插件,感谢支持。