Unity 性能分析小工具
下文有两个方法,分别是一段检测执行过程耗费时间的代码,还有一个是保存和加载Unity Profiler 的代码(因为UnityProfiler 只能显示一部分的数据,如果运行时间长的话有部分分析数据查看不到)
1. 检测执行耗费时间 代码如下:
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using UnityEngine; public class CustomTimer : IDisposable { private string m_timerName; private int m_numTests; private Stopwatch m_watch; public CustomTimer(string timerName,int numTests) { m_timerName = timerName; m_numTests = numTests; if (m_numTests <= 0) m_numTests = 1; m_watch = Stopwatch.StartNew(); } public void Dispose() { m_watch.Stop(); float ms = m_watch.ElapsedMilliseconds; UnityEngine.Debug.Log(string.Format("{0} finished: {1:0.00}ms total , {2:0.00000}ms per test for {3} tests", m_timerName, ms, ms / m_numTests, m_numTests)); } }
使用方法如下: 在程序块里放入自己要检测的代码,在循环使用的时候,把0改成循环的次数就可以了
using (new CustomTimer("My Test", 0)) { using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url)) { yield return request.SendWebRequest(); if (request.isHttpError || request.isNetworkError) { // 下载出错 print(request.error); } else { // 下载完成 AssetBundle assetBundle = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle; GameObject obj = assetBundle.LoadAsset<GameObject>(assetBundle.GetAllAssetNames()[0]); GameObject obj2 = GameObject.Instantiate(obj); this.obj = obj2.transform; // 优先释放request 会降低内存峰值 request.Dispose(); } } }
2. Unity Profiler 保存方法:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
public class ProfilerDataSaverComponent : MonoBehaviour
{
int _count = 0;
void Start()
{
Profiler.logFile = "";
}
// Update is called once per frame
void Update()
{
if(Input.GetKey(KeyCode.LeftControl)&& Input.GetKeyDown(KeyCode.H))
{
StartCoroutine(SaveProfilerData());
}
}
IEnumerator SaveProfilerData()
{
while(true)
{
string filepath = Application.persistentDataPath + "/profilerLog" + _count;
Profiler.logFile = filepath;
Profiler.enableBinaryLog = true;
Profiler.enabled = true;
for (int i = 0; i < 300; i++)
{
yield return new WaitForEndOfFrame();
if(!Profiler.enabled)
{
Profiler.enabled = true;
}
}
_count++;
}
}
}
读取保存的UnityProfiler数据: 在Window/ProfilerDataLoader 内
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
public class ProfilerDataLoaderWindow : EditorWindow
{
static List<string> s_cachedFilePaths;
static int s_chosenIndex = -1;
[MenuItem("Window/ProfilerDataLoader")]
static void Init()
{
ProfilerDataLoaderWindow window = (ProfilerDataLoaderWindow)EditorWindow.GetWindow(typeof(ProfilerDataLoaderWindow));
}
static void ReadProfilerDataFiles()
{
Profiler.logFile = "";
string[] filePath = Directory.GetFiles(Application.persistentDataPath , "ProfilerLog*");
s_cachedFilePaths = new List<string>();
Regex test = new Regex(".data$");
for (int i = 0; i < filePath.Length; i++)
{
string thisPath = filePath[i];
Match match = test.Match(thisPath);
if(!match.Success)
{
Debug.Log("Found file: " + thisPath);
s_cachedFilePaths.Add(thisPath);
}
}
s_chosenIndex = -1;
}
private void OnGUI()
{
if(GUILayout.Button("Find Files"))
{
ReadProfilerDataFiles();
}
if (s_cachedFilePaths == null)
return;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Files");
EditorGUILayout.BeginHorizontal();
GUIStyle defaultStyle = new GUIStyle(GUI.skin.button);
defaultStyle.fixedWidth = 40;
GUIStyle highlightedStyle = new GUIStyle(defaultStyle);
highlightedStyle.normal.textColor = Color.red;
for (int i = 0; i < s_cachedFilePaths.Count; i++)
{
if(i%5==0)
{
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
}
GUIStyle thisStyle = null;
if(s_chosenIndex ==i)
{
thisStyle = highlightedStyle;
}
else
{
thisStyle = defaultStyle;
}
if (GUILayout.Button("" + i, thisStyle))
{
Profiler.AddFramesFromFile(s_cachedFilePaths[i]);
s_chosenIndex = i;
}
}
EditorGUILayout.EndHorizontal();
}
}

浙公网安备 33010602011771号