Working single-purpose object pooling solution
This commit is contained in:
@@ -15,7 +15,7 @@ namespace Minigames.DivingForPictures
|
||||
public List<GameObject> tilePrefabs;
|
||||
|
||||
[Header("Tile Settings")]
|
||||
private const float TileHeight = 5f; // Set to match prefab height
|
||||
private Dictionary<GameObject, float> _tileHeights = new Dictionary<GameObject, float>();
|
||||
public int initialTileCount = 3;
|
||||
public float tileSpawnBuffer = 1f;
|
||||
|
||||
@@ -23,6 +23,14 @@ namespace Minigames.DivingForPictures
|
||||
public float moveSpeed = 3f;
|
||||
public float speedUpFactor = 0.2f;
|
||||
public float speedUpInterval = 10f;
|
||||
public float maxMoveSpeed = 12f; // Added a cap to the movement speed
|
||||
|
||||
[Header("Object Pooling")]
|
||||
public bool useObjectPooling = true;
|
||||
public bool preInstantiateTiles = false; // Added option to control pre-instantiation
|
||||
public int initialTilesPerPrefab = 2;
|
||||
public int maxPerPrefabPoolSize = 2;
|
||||
public int totalMaxPoolSize = 10; // Total pool size across all prefab types
|
||||
|
||||
[FormerlySerializedAs("OnTileSpawned")] [Header("Events")]
|
||||
public UnityEvent<GameObject> onTileSpawned;
|
||||
@@ -37,14 +45,61 @@ namespace Minigames.DivingForPictures
|
||||
private Camera _mainCamera;
|
||||
private float _screenBottom;
|
||||
private float _screenTop;
|
||||
private TrenchTilePool _tilePool;
|
||||
|
||||
private const float TileSpawnZ = -1f; // All spawned tiles should have z = -1
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
|
||||
// Calculate tile heights for each prefab
|
||||
foreach (var prefab in tilePrefabs)
|
||||
{
|
||||
Renderer renderer = prefab.GetComponentInChildren<Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
_tileHeights[prefab] = renderer.bounds.size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback in case no renderer is found
|
||||
_tileHeights[prefab] = 5f;
|
||||
Debug.LogWarning($"No renderer found in prefab {prefab.name}. Using default height of 5.");
|
||||
}
|
||||
}
|
||||
|
||||
if (useObjectPooling)
|
||||
{
|
||||
// Create the tile pool
|
||||
GameObject poolGO = new GameObject("TrenchTilePool");
|
||||
poolGO.transform.SetParent(transform);
|
||||
_tilePool = poolGO.AddComponent<TrenchTilePool>();
|
||||
_tilePool.preInstantiateTiles = preInstantiateTiles;
|
||||
_tilePool.initialTilesPerPrefab = initialTilesPerPrefab;
|
||||
_tilePool.maxPerPrefabPoolSize = maxPerPrefabPoolSize;
|
||||
_tilePool.totalMaxPoolSize = totalMaxPoolSize;
|
||||
_tilePool.Initialize(tilePrefabs);
|
||||
|
||||
// Periodically trim the pool to optimize memory usage
|
||||
InvokeRepeating(nameof(TrimExcessPooledTiles), 10f, 30f);
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
CalculateScreenBounds();
|
||||
for (int i = 0; i < initialTileCount; i++)
|
||||
{
|
||||
SpawnTileAtY(_screenBottom + i * TileHeight);
|
||||
float y = _screenBottom;
|
||||
// Calculate proper Y position based on previous tiles
|
||||
if (i > 0 && _activeTiles.Count > 0)
|
||||
{
|
||||
GameObject prevTile = _activeTiles[_activeTiles.Count - 1];
|
||||
float prevHeight = GetTileHeight(prevTile);
|
||||
y = prevTile.transform.position.y - prevHeight;
|
||||
}
|
||||
SpawnTileAtY(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +135,29 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
if (_activeTiles.Count == 0) return;
|
||||
GameObject topTile = _activeTiles[0];
|
||||
if (topTile.transform.position.y - TileHeight / 2 > _screenTop + tileSpawnBuffer)
|
||||
float tileHeight = GetTileHeight(topTile);
|
||||
if (topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer)
|
||||
{
|
||||
_activeTiles.RemoveAt(0);
|
||||
onTileDestroyed?.Invoke(topTile);
|
||||
Destroy(topTile);
|
||||
|
||||
if (useObjectPooling && _tilePool != null)
|
||||
{
|
||||
// Find the prefab index for this tile
|
||||
int prefabIndex = GetPrefabIndex(topTile);
|
||||
if (prefabIndex >= 0)
|
||||
{
|
||||
_tilePool.ReturnTile(topTile, prefabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(topTile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(topTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,10 +165,11 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
if (_activeTiles.Count == 0) return;
|
||||
GameObject bottomTile = _activeTiles[^1];
|
||||
float bottomEdge = bottomTile.transform.position.y - TileHeight / 2;
|
||||
float tileHeight = GetTileHeight(bottomTile);
|
||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||
if (bottomEdge > _screenBottom - tileSpawnBuffer)
|
||||
{
|
||||
float newY = bottomTile.transform.position.y - TileHeight;
|
||||
float newY = bottomTile.transform.position.y - tileHeight;
|
||||
SpawnTileAtY(newY);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +179,7 @@ namespace Minigames.DivingForPictures
|
||||
_speedUpTimer += Time.deltaTime;
|
||||
if (_speedUpTimer >= speedUpInterval)
|
||||
{
|
||||
moveSpeed += speedUpFactor;
|
||||
moveSpeed = Mathf.Min(moveSpeed + speedUpFactor, maxMoveSpeed);
|
||||
_speedUpTimer = 0f;
|
||||
}
|
||||
}
|
||||
@@ -114,8 +188,21 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
int prefabIndex = GetWeightedRandomTileIndex();
|
||||
GameObject prefab = tilePrefabs[prefabIndex];
|
||||
// Use the prefab's original rotation
|
||||
GameObject tile = Instantiate(prefab, new Vector3(0f, y, 0f), prefab.transform.rotation, transform);
|
||||
GameObject tile;
|
||||
|
||||
if (useObjectPooling && _tilePool != null)
|
||||
{
|
||||
tile = _tilePool.GetTile(prefabIndex);
|
||||
tile.transform.position = new Vector3(0f, y, TileSpawnZ);
|
||||
tile.transform.rotation = prefab.transform.rotation;
|
||||
tile.transform.SetParent(transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the prefab's original rotation
|
||||
tile = Instantiate(prefab, new Vector3(0f, y, TileSpawnZ), prefab.transform.rotation, transform);
|
||||
}
|
||||
|
||||
_activeTiles.Add(tile);
|
||||
_tileLastUsed[prefabIndex] = _spawnCounter++;
|
||||
onTileSpawned?.Invoke(tile);
|
||||
@@ -143,6 +230,65 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
return Random.Range(0, n); // fallback
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of a tile based on its prefab or renderer bounds
|
||||
/// </summary>
|
||||
/// <param name="tile">The tile to measure</param>
|
||||
/// <returns>The height of the tile</returns>
|
||||
private float GetTileHeight(GameObject tile)
|
||||
{
|
||||
// Check if this is a known prefab
|
||||
foreach (var prefab in tilePrefabs)
|
||||
{
|
||||
// Check if this tile was created from this prefab
|
||||
if (tile.name.StartsWith(prefab.name))
|
||||
{
|
||||
if (_tileHeights.TryGetValue(prefab, out float height))
|
||||
{
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, calculate it from the renderer
|
||||
Renderer renderer = tile.GetComponentInChildren<Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
return renderer.bounds.size.y;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return 5f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the prefab that was used to create this tile
|
||||
/// </summary>
|
||||
/// <param name="tile">The tile to check</param>
|
||||
/// <returns>The index of the prefab or -1 if not found</returns>
|
||||
private int GetPrefabIndex(GameObject tile)
|
||||
{
|
||||
for (int i = 0; i < tilePrefabs.Count; i++)
|
||||
{
|
||||
if (tile.name.StartsWith(tilePrefabs[i].name))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called periodically to trim excess pooled tiles
|
||||
/// </summary>
|
||||
private void TrimExcessPooledTiles()
|
||||
{
|
||||
if (_tilePool != null)
|
||||
{
|
||||
_tilePool.TrimExcess();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected()
|
||||
@@ -151,8 +297,13 @@ namespace Minigames.DivingForPictures
|
||||
Gizmos.color = Color.cyan;
|
||||
for (int i = 0; i < initialTileCount; i++)
|
||||
{
|
||||
Vector3 center = new Vector3(0f, _screenBottom + i * TileHeight, 0f);
|
||||
Gizmos.DrawWireCube(center, new Vector3(10f, TileHeight, 1f));
|
||||
float height = 5f;
|
||||
if (tilePrefabs.Count > 0 && _tileHeights.TryGetValue(tilePrefabs[0], out float h))
|
||||
{
|
||||
height = h;
|
||||
}
|
||||
Vector3 center = new Vector3(0f, _screenBottom + i * height, 0f);
|
||||
Gizmos.DrawWireCube(center, new Vector3(10f, height, 1f));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user