Added ProfilerWindow
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9a1f5463ef6a4249af45548d72f211c6
|
|
||||||
timeCreated: 1769189971
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PashaBibko.Pacore.Editor.Drawers
|
|
||||||
{
|
|
||||||
public sealed class DisabledGUIBlock : IDisposable
|
|
||||||
{
|
|
||||||
public DisabledGUIBlock() => GUI.enabled = false;
|
|
||||||
public void Dispose() => GUI.enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3d8664e5ad044a248710d9b31044d2fc
|
|
||||||
timeCreated: 1769189984
|
|
||||||
@@ -11,11 +11,12 @@ namespace PashaBibko.Pacore.Editor.Drawers
|
|||||||
{
|
{
|
||||||
if (attribute is InspectorReadOnlyAttribute readOnlyAttribute)
|
if (attribute is InspectorReadOnlyAttribute readOnlyAttribute)
|
||||||
{
|
{
|
||||||
using (new DisabledGUIBlock())
|
GUI.enabled = false;
|
||||||
{
|
|
||||||
label.text = readOnlyAttribute.Name ?? label.text; // Uses custom name if it exists
|
label.text = readOnlyAttribute.Name ?? label.text; // Uses custom name if it exists
|
||||||
EditorGUI.PropertyField(position, property, label);
|
EditorGUI.PropertyField(position, property, label);
|
||||||
}
|
|
||||||
|
GUI.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
Assets/Pacore/Editor/EditorWindows.meta
Normal file
3
Assets/Pacore/Editor/EditorWindows.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d9b025c89af342a3b3cfc696a32fdb2e
|
||||||
|
timeCreated: 1769285442
|
||||||
97
Assets/Pacore/Editor/EditorWindows/ProfilerWindow.cs
Normal file
97
Assets/Pacore/Editor/EditorWindows/ProfilerWindow.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using PashaBibko.Pacore.DevTools;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Pacore.Editor.EditorWindows
|
||||||
|
{
|
||||||
|
public class ProfilerWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private double LastRepaint = double.MinValue;
|
||||||
|
private Vector2 ScrollPosition;
|
||||||
|
|
||||||
|
[MenuItem("Pacore/Profiler")]
|
||||||
|
public static void OpenWindow() => GetWindow<ProfilerWindow>();
|
||||||
|
|
||||||
|
/* Makes sure the window is repainted often to show latest info */
|
||||||
|
private void OnDisable() => EditorApplication.update -= CheckForRepaint;
|
||||||
|
private void OnEnable() => EditorApplication.update += CheckForRepaint;
|
||||||
|
|
||||||
|
private void CheckForRepaint()
|
||||||
|
{
|
||||||
|
/* Triggers a repaint when it has been over 1 second since last repaint */
|
||||||
|
double now = EditorApplication.timeSinceStartup;
|
||||||
|
if (now - LastRepaint > 1f)
|
||||||
|
{
|
||||||
|
LastRepaint = now;
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawEmptyProfiler()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical(style: "box");
|
||||||
|
|
||||||
|
GUILayout.Label(text: "No profiler snippets found", EditorStyles.boldLabel);
|
||||||
|
GUILayout.Label(text: "Try running the game to collect profile samples");
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawProfilerSnippet(string name, List<long> times)
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical(style: "box");
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Label(text: name, EditorStyles.boldLabel);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
float averageMs = times.Sum() / (float)times.Count;
|
||||||
|
GUILayout.Label("Average time: " + averageMs);
|
||||||
|
|
||||||
|
IGrouping<long, long>[] ordered = times // List<long>
|
||||||
|
.GroupBy(time => time) // IEnumerable<IGrouping<long, long>>
|
||||||
|
.OrderByDescending(time => time.Key) // IOrdererEnumerable<IGrouping<long, long>>
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
foreach (IGrouping<long, long> group in ordered)
|
||||||
|
{
|
||||||
|
string text = group.Count() > 1
|
||||||
|
? $"- {group.Key}ms {group.Count()}x"
|
||||||
|
: $"- {group.Key}ms";
|
||||||
|
|
||||||
|
GUILayout.Label(text, EditorStyles.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draws the different snippets to the screen */
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
GUILayout.Space(5); // Stops the window rendering right at the top
|
||||||
|
IReadOnlyDictionary<string, List<long>> snippets = CodeProfiler.GetProfilerSnippets();
|
||||||
|
|
||||||
|
/* If there are no snippets, draws an inspector with instructions */
|
||||||
|
if (snippets.Count == 0)
|
||||||
|
{
|
||||||
|
DrawEmptyProfiler();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draws a quick overview of all snippets found */
|
||||||
|
GUILayout.BeginVertical(style: "box");
|
||||||
|
GUILayout.Label(text: $"[{snippets.Count}] different profiler snippets found");
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
/* Draws each profiler snippet */
|
||||||
|
ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);
|
||||||
|
foreach (KeyValuePair<string, List<long>> snippet in snippets)
|
||||||
|
{
|
||||||
|
DrawProfilerSnippet(snippet.Key, snippet.Value);
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5bd8cdd7db4d4436978e97bda9cdc0cb
|
||||||
|
timeCreated: 1769285452
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using System.Threading;
|
||||||
using PashaBibko.Pacore.Attributes;
|
using PashaBibko.Pacore.Attributes;
|
||||||
|
using PashaBibko.Pacore.DevTools;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
[CreateInstanceOnStart] public class TestMonoBehaviour : MonoBehaviour
|
[CreateInstanceOnStart] public class TestMonoBehaviour : MonoBehaviour
|
||||||
@@ -12,6 +14,20 @@ using UnityEngine;
|
|||||||
|
|
||||||
private void OnTestChange() => LogTestValue();
|
private void OnTestChange() => LogTestValue();
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
using (CodeProfiler.Start("Test Snippet"))
|
||||||
|
{
|
||||||
|
SpinWait sw = new();
|
||||||
|
int count = Random.Range(1, 50);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
sw.SpinOnce();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[InspectorCallable(nameof(LogSpawnableType))]
|
[InspectorCallable(nameof(LogSpawnableType))]
|
||||||
public void LogSpawnableType()
|
public void LogSpawnableType()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user