ParticleEffectForUGUI/Samples~/Performance Demo/NanoMonitor/Scripts/NanoMonitor.cs

297 lines
7.8 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Serialization;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
#endif
namespace Coffee.NanoMonitor
{
#if UNITY_EDITOR
[CustomEditor(typeof(NanoMonitor))]
internal class NanoMonitorEditor : Editor
{
private ReorderableList _monitorItemList;
private void OnEnable()
{
var items = serializedObject.FindProperty("m_CustomMonitorItems");
_monitorItemList = new ReorderableList(serializedObject, items)
{
draggable = false,
drawHeaderCallback = r =>
{
EditorGUI.LabelField(r, new GUIContent("Custom Monitor Items"));
},
drawElementCallback = (r, i, _, __) =>
{
EditorGUI.LabelField(new Rect(r.x, r.y, r.width, r.height - 2), GUIContent.none,
EditorStyles.textArea);
var labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 80;
EditorGUI.PropertyField(new Rect(r.x + 2, r.y + 3, r.width - 4, r.height - 4),
items.GetArrayElementAtIndex(i), true);
EditorGUIUtility.labelWidth = labelWidth;
},
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6
};
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
_monitorItemList.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
#endif
[DisallowMultipleComponent]
public sealed class NanoMonitor : MonoBehaviour
{
//################################
// Serialize Members.
//################################
// Settings
[Header("Settings")]
[SerializeField]
[Range(0.01f, 2f)]
private float m_Interval = 1f;
[SerializeField]
[Range(0, 3)]
private int m_Precision = 2;
[SerializeField]
private Font m_Font;
// Foldout
[Header("Foldout")]
[SerializeField]
private bool m_Opened;
[FormerlySerializedAs("m_Collapse")]
[SerializeField]
private GameObject m_FoldoutObject;
[SerializeField]
private Button m_OpenButton;
[SerializeField]
private Button m_CloseButton;
// View
[Header("View")]
[SerializeField]
private MonitorUI m_Fps;
[SerializeField]
private MonitorUI m_Gc;
[SerializeField]
private MonitorUI m_MonoUsage;
[SerializeField]
private MonitorUI m_UnityUsage;
[HideInInspector]
[SerializeField]
private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
//################################
// Private Members.
//################################
private double _elapsed;
private double _fpsElapsed;
private int _frames;
private void Update()
{
_frames++;
_elapsed += Time.unscaledDeltaTime;
_fpsElapsed += Time.unscaledDeltaTime;
if (_elapsed < m_Interval) return;
if (m_Fps)
{
m_Fps.SetText("FPS: {0}", (int)(_frames / _fpsElapsed));
}
if (m_Gc)
{
m_Gc.SetText("GC: {0}", GC.CollectionCount(0));
}
if (m_MonoUsage)
{
var monoUsed = (Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
var monoTotal = (Profiler.GetMonoHeapSizeLong() >> 10) / 1024f;
if (m_Precision == 3)
{
m_MonoUsage.SetText("Mono: {0:N3}/{1:N3}MB", monoUsed, monoTotal);
}
else if (m_Precision == 2)
{
m_MonoUsage.SetText("Mono: {0:N2}/{1:N2}MB", monoUsed, monoTotal);
}
else if (m_Precision == 1)
{
m_MonoUsage.SetText("Mono: {0:N1}/{1:N1}MB", monoUsed, monoTotal);
}
else
{
m_MonoUsage.SetText("Mono: {0:N0}/{1:N0}MB", monoUsed, monoTotal);
}
}
if (m_UnityUsage)
{
var unityUsed = (Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
var unityTotal = (Profiler.GetTotalReservedMemoryLong() >> 10) / 1024f;
if (m_Precision == 3)
{
m_UnityUsage.SetText("Unity: {0:N3}/{1:N3}MB", unityUsed, unityTotal);
}
else if (m_Precision == 2)
{
m_UnityUsage.SetText("Unity: {0:N2}/{1:N2}MB", unityUsed, unityTotal);
}
else if (m_Precision == 1)
{
m_UnityUsage.SetText("Unity: {0:N1}/{1:N1}MB", unityUsed, unityTotal);
}
else
{
m_UnityUsage.SetText("Unity: {0:N0}/{1:N0}MB", unityUsed, unityTotal);
}
}
foreach (var item in m_CustomMonitorItems)
{
item.UpdateText();
}
_frames = 0;
_elapsed %= m_Interval;
_fpsElapsed = 0;
}
//################################
// Unity Callbacks.
//################################
private void OnEnable()
{
if (m_OpenButton)
{
m_OpenButton.onClick.AddListener(Open);
}
if (m_CloseButton)
{
m_CloseButton.onClick.AddListener(Close);
}
if (m_Opened)
{
Open();
}
else
{
Close();
}
}
private void OnDisable()
{
if (m_OpenButton)
{
m_OpenButton.onClick.RemoveListener(Open);
}
if (m_CloseButton)
{
m_CloseButton.onClick.RemoveListener(Close);
}
}
#if UNITY_EDITOR
private void OnValidate()
{
if (m_Font)
{
foreach (var ui in GetComponentsInChildren<MonitorUI>(true))
{
ui.font = m_Font;
}
}
if (m_Opened)
{
Open();
}
else
{
Close();
}
}
#endif
//################################
// Public Members.
//################################
public void Clean()
{
Resources.UnloadUnusedAssets();
GC.Collect();
}
private void Open()
{
_frames = 0;
_elapsed = m_Interval;
_fpsElapsed = 0;
if (m_FoldoutObject)
{
m_FoldoutObject.SetActive(true);
}
if (m_CloseButton)
{
m_CloseButton.gameObject.SetActive(true);
}
if (m_OpenButton)
{
m_OpenButton.gameObject.SetActive(false);
}
}
private void Close()
{
if (m_FoldoutObject)
{
m_FoldoutObject.SetActive(false);
}
if (m_CloseButton)
{
m_CloseButton.gameObject.SetActive(false);
}
if (m_OpenButton)
{
m_OpenButton.gameObject.SetActive(true);
}
}
}
}