Working single-purpose object pooling solution

This commit is contained in:
Michal Pikulski
2025-09-16 12:23:25 +02:00
parent 2c56d0e1de
commit bcc6f05058
19 changed files with 990 additions and 115 deletions

View File

@@ -0,0 +1,244 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using Minigames.DivingForPictures;
namespace Editor.Utilities
{
public class PoolMonitorWindow : EditorWindow
{
private Vector2 scrollPosition;
private bool autoRefresh = true;
private float refreshInterval = 1.0f;
private float lastRefreshTime;
private bool showTrenchTiles = true;
private bool showBubbles = true;
[MenuItem("Tools/Pool Monitor")]
public static void ShowWindow()
{
GetWindow<PoolMonitorWindow>("Pool Monitor");
}
void OnGUI()
{
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Object Pool Monitor", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
autoRefresh = EditorGUILayout.Toggle("Auto Refresh", autoRefresh);
if (autoRefresh)
{
refreshInterval = EditorGUILayout.Slider("Refresh Interval", refreshInterval, 0.1f, 5f);
}
if (GUILayout.Button("Refresh Now"))
{
RefreshPoolInfo();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Display toggles for showing different pool types
EditorGUILayout.BeginHorizontal();
showTrenchTiles = EditorGUILayout.ToggleLeft("Show Trench Tile Pools", showTrenchTiles, GUILayout.Width(200));
showBubbles = EditorGUILayout.ToggleLeft("Show Bubble Pools", showBubbles, GUILayout.Width(200));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
if (Application.isPlaying)
{
DisplayPoolInfo();
}
else
{
EditorGUILayout.HelpBox("Enter play mode to see pool statistics.", MessageType.Info);
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
void Update()
{
if (autoRefresh && Application.isPlaying)
{
float currentTime = (float)EditorApplication.timeSinceStartup;
if (currentTime - lastRefreshTime > refreshInterval)
{
lastRefreshTime = currentTime;
RefreshPoolInfo();
Repaint();
}
}
}
void RefreshPoolInfo()
{
if (!Application.isPlaying) return;
// Call LogPoolStats on all pool instances to update their stats in the console
if (showTrenchTiles)
{
TrenchTilePool[] tilePools = Object.FindObjectsByType<TrenchTilePool>(FindObjectsSortMode.None);
foreach (var pool in tilePools)
{
pool.LogPoolStats();
}
}
if (showBubbles)
{
BubblePool[] bubblePools = Object.FindObjectsByType<BubblePool>(FindObjectsSortMode.None);
foreach (var pool in bubblePools)
{
if (pool != null && pool.gameObject.activeInHierarchy)
{
// If BubblePool has a LogPoolStats method, call it
var logMethod = typeof(BubblePool).GetMethod("LogPoolStats");
if (logMethod != null)
{
logMethod.Invoke(pool, null);
}
}
}
}
}
void DisplayPoolInfo()
{
EditorGUILayout.LabelField("Scene Statistics:", EditorStyles.boldLabel);
EditorGUILayout.LabelField($"Total GameObjects: {Object.FindObjectsByType<GameObject>(FindObjectsSortMode.None).Length}");
EditorGUILayout.Space();
if (showTrenchTiles)
{
DisplayTrenchTilePoolInfo();
}
if (showBubbles)
{
DisplayBubblePoolInfo();
}
}
void DisplayTrenchTilePoolInfo()
{
TrenchTilePool[] pools = Object.FindObjectsByType<TrenchTilePool>(FindObjectsSortMode.None);
if (pools.Length == 0)
{
EditorGUILayout.HelpBox("No trench tile pools found in the scene.", MessageType.Info);
}
else
{
EditorGUILayout.LabelField("Trench Tile Pools", EditorStyles.boldLabel);
foreach (var pool in pools)
{
EditorGUILayout.LabelField($"Pool: {pool.name}", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
// Get private field values using reflection
System.Reflection.FieldInfo totalCountField = typeof(TrenchTilePool).GetField("totalPooledCount",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
System.Reflection.FieldInfo pooledTilesField = typeof(TrenchTilePool).GetField("pooledTiles",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
System.Reflection.FieldInfo prefabUsageField = typeof(TrenchTilePool).GetField("prefabUsageCount",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (totalCountField != null)
{
int totalCount = (int)totalCountField.GetValue(pool);
EditorGUILayout.LabelField($"Total Pooled Objects: {totalCount}/{pool.totalMaxPoolSize}");
}
if (pooledTilesField != null && prefabUsageField != null)
{
var pooledTiles = pooledTilesField.GetValue(pool) as Dictionary<int, Stack<GameObject>>;
var usageCounts = prefabUsageField.GetValue(pool) as Dictionary<int, int>;
if (pooledTiles != null)
{
EditorGUILayout.LabelField("Prefab Details:", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
foreach (var entry in pooledTiles)
{
int prefabIndex = entry.Key;
Stack<GameObject> stack = entry.Value;
int count = stack != null ? stack.Count : 0;
int usageCount = 0;
if (usageCounts != null && usageCounts.TryGetValue(prefabIndex, out int usage))
{
usageCount = usage;
}
EditorGUILayout.LabelField($"Prefab {prefabIndex}: {count} pooled, {usageCount} usages");
}
EditorGUI.indentLevel--;
}
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
}
}
void DisplayBubblePoolInfo()
{
BubblePool[] pools = Object.FindObjectsByType<BubblePool>(FindObjectsSortMode.None);
if (pools.Length == 0)
{
EditorGUILayout.HelpBox("No bubble pools found in the scene.", MessageType.Info);
}
else
{
EditorGUILayout.LabelField("Bubble Pools", EditorStyles.boldLabel);
foreach (var pool in pools)
{
EditorGUILayout.LabelField($"Pool: {pool.name}", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
// Get private field values using reflection
System.Reflection.FieldInfo pooledBubblesField = typeof(BubblePool).GetField("pooledBubbles",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (pooledBubblesField != null)
{
var pooledBubbles = pooledBubblesField.GetValue(pool) as Stack<Bubble>;
int count = pooledBubbles != null ? pooledBubbles.Count : 0;
EditorGUILayout.LabelField($"Pooled Bubbles: {count}/{pool.maxPoolSize}");
EditorGUILayout.LabelField($"Initial Pool Size: {pool.initialPoolSize}");
}
// Try to find active bubbles in the scene
Bubble[] activeBubbles = Object.FindObjectsByType<Bubble>(FindObjectsSortMode.None);
int activeBubbleCount = 0;
foreach (var bubble in activeBubbles)
{
if (bubble.gameObject.activeInHierarchy)
{
activeBubbleCount++;
}
}
EditorGUILayout.LabelField($"Active Bubbles: {activeBubbleCount}");
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
}
}
}
}