IMplement basic Developer Settings

This commit is contained in:
2025-09-24 12:21:21 +02:00
parent f07ce88331
commit 8b96a5d0c3
18 changed files with 739 additions and 248 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Pooling;
using AppleHills.Core.Settings;
namespace Minigames.DivingForPictures
{
@@ -16,50 +17,17 @@ namespace Minigames.DivingForPictures
[Tooltip("List of possible obstacle prefabs to spawn")]
[SerializeField] private List<GameObject> obstaclePrefabs;
[Header("Spawn Settings")]
[Tooltip("Time interval between spawn attempts (in seconds)")]
[SerializeField] private float spawnInterval = 2f;
[Tooltip("Random variation in spawn timing (+/- seconds)")]
[SerializeField] private float spawnIntervalVariation = 0.5f;
[Tooltip("Maximum number of spawn position attempts before skipping")]
[SerializeField] private int maxSpawnAttempts = 10;
[Tooltip("Radius around spawn point to check for tile collisions")]
[SerializeField] private float spawnCollisionRadius = 1f;
[Header("Obstacle Properties Randomization")]
[Tooltip("Minimum movement speed for spawned obstacles")]
[SerializeField] private float minMoveSpeed = 1f;
[Tooltip("Maximum movement speed for spawned obstacles")]
[SerializeField] private float maxMoveSpeed = 4f;
[Header("Object Pooling")]
[Tooltip("Whether to use object pooling for obstacles")]
[SerializeField] private bool useObjectPooling = true;
[Tooltip("Maximum objects per prefab type in pool")]
[SerializeField] private int maxPerPrefabPoolSize = 3;
[Tooltip("Total maximum pool size across all prefab types")]
[SerializeField] private int totalMaxPoolSize = 15;
[Header("Layer Settings")]
[Tooltip("Layer mask for tile collision detection during spawn position validation")]
[SerializeField] private LayerMask tileLayerMask = -1; // Let user configure which layers to avoid
[Tooltip("Target layer for spawned obstacles - obstacles will be placed on this layer")]
[SerializeField] private int obstacleLayer = 11; // Default to layer 11, but configurable
[Header("Events")]
[Tooltip("Called when an obstacle is spawned")]
[Tooltip("Invoked when a new obstacle is spawned")]
public UnityEvent<GameObject> onObstacleSpawned;
[Tooltip("Called when an obstacle is returned to pool")]
[Tooltip("Invoked when an obstacle is destroyed or returned to pool")]
public UnityEvent<GameObject> onObstacleDestroyed;
// Settings references
private IDivingMinigameSettings _settings;
private DivingDeveloperSettings _devSettings;
// Private fields
private ObstaclePool _obstaclePool;
private Camera _mainCamera;
@@ -75,13 +43,34 @@ namespace Minigames.DivingForPictures
{
_mainCamera = Camera.main;
// Get settings from GameManager
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
_devSettings = GameManager.GetDeveloperSettings<DivingDeveloperSettings>();
if (_settings == null)
{
Debug.LogError("[ObstacleSpawner] Failed to load diving minigame settings!");
}
if (_devSettings == null)
{
Debug.LogError("[ObstacleSpawner] Failed to load diving developer settings!");
}
// Validate obstacle prefabs
ValidateObstaclePrefabs();
if (useObjectPooling)
if (_devSettings?.ObstacleUseObjectPooling ?? false)
{
InitializeObjectPool();
}
// Initialize events if null
if (onObstacleSpawned == null)
onObstacleSpawned = new UnityEvent<GameObject>();
if (onObstacleDestroyed == null)
onObstacleDestroyed = new UnityEvent<GameObject>();
}
private void Start()
@@ -100,6 +89,8 @@ namespace Minigames.DivingForPictures
/// </summary>
private void ValidateObstaclePrefabs()
{
if (_devSettings == null) return;
for (int i = 0; i < obstaclePrefabs.Count; i++)
{
if (obstaclePrefabs[i] == null) continue;
@@ -112,10 +103,10 @@ namespace Minigames.DivingForPictures
}
// Ensure the prefab is on the correct layer (using configurable obstacleLayer)
if (obstaclePrefabs[i].layer != obstacleLayer)
if (obstaclePrefabs[i].layer != _devSettings.ObstacleLayer)
{
Debug.LogWarning($"Obstacle prefab {obstaclePrefabs[i].name} is not on the configured obstacle layer ({obstacleLayer}). Setting layer automatically.");
SetLayerRecursively(obstaclePrefabs[i], obstacleLayer);
Debug.LogWarning($"Obstacle prefab {obstaclePrefabs[i].name} is not on the configured obstacle layer ({_devSettings.ObstacleLayer}). Setting layer automatically.");
SetLayerRecursively(obstaclePrefabs[i], _devSettings.ObstacleLayer);
}
}
}
@@ -142,8 +133,8 @@ namespace Minigames.DivingForPictures
_obstaclePool = poolGO.AddComponent<ObstaclePool>();
// Set up pool configuration
_obstaclePool.maxPerPrefabPoolSize = maxPerPrefabPoolSize;
_obstaclePool.totalMaxPoolSize = totalMaxPoolSize;
_obstaclePool.maxPerPrefabPoolSize = _devSettings.ObstacleMaxPerPrefabPoolSize;
_obstaclePool.totalMaxPoolSize = _devSettings.ObstacleTotalMaxPoolSize;
// Convert GameObject list to FloatingObstacle list
List<FloatingObstacle> prefabObstacles = new List<FloatingObstacle>(obstaclePrefabs.Count);
@@ -230,7 +221,9 @@ namespace Minigames.DivingForPictures
while (true)
{
// Calculate next spawn time with variation
float nextSpawnTime = spawnInterval + Random.Range(-spawnIntervalVariation, spawnIntervalVariation);
float nextSpawnTime = _settings.EndlessDescenderObstacleSpawnInterval +
Random.Range(-_settings.EndlessDescenderObstacleSpawnIntervalVariation,
_settings.EndlessDescenderObstacleSpawnIntervalVariation);
nextSpawnTime = Mathf.Max(0.1f, nextSpawnTime); // Ensure minimum interval
yield return new WaitForSeconds(nextSpawnTime);
@@ -264,7 +257,7 @@ namespace Minigames.DivingForPictures
bool foundValidPosition = false;
// Try to find a valid spawn position
for (int attempts = 0; attempts < maxSpawnAttempts; attempts++)
for (int attempts = 0; attempts < _settings.EndlessDescenderObstacleMaxSpawnAttempts; attempts++)
{
spawnPosition = GetRandomSpawnPosition();
@@ -277,13 +270,13 @@ namespace Minigames.DivingForPictures
}
else
{
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{maxSpawnAttempts})");
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{_settings.EndlessDescenderObstacleMaxSpawnAttempts})");
}
}
if (!foundValidPosition)
{
Debug.LogWarning($"[ObstacleSpawner] SPAWN MISSED: Could not find valid spawn position after {maxSpawnAttempts} attempts at {Time.time:F2}");
Debug.LogWarning($"[ObstacleSpawner] SPAWN MISSED: Could not find valid spawn position after {_settings.EndlessDescenderObstacleMaxSpawnAttempts} attempts at {Time.time:F2}");
}
}
@@ -306,7 +299,7 @@ namespace Minigames.DivingForPictures
private bool IsValidSpawnPosition(Vector3 position)
{
// Use OverlapCircle to check for collisions with tiles
Collider2D collision = Physics2D.OverlapCircle(position, spawnCollisionRadius, tileLayerMask);
Collider2D collision = Physics2D.OverlapCircle(position, _settings.EndlessDescenderObstacleSpawnCollisionRadius, _devSettings.ObstacleTileLayerMask);
return collision == null;
}
@@ -330,7 +323,7 @@ namespace Minigames.DivingForPictures
GameObject obstacle;
// Spawn using pool or instantiate directly
if (useObjectPooling && _obstaclePool != null)
if (_devSettings.ObstacleUseObjectPooling && _obstaclePool != null)
{
Debug.Log($"[ObstacleSpawner] Requesting obstacle from pool (prefab index {prefabIndex})");
obstacle = _obstaclePool.GetObstacle(prefabIndex);
@@ -416,8 +409,10 @@ namespace Minigames.DivingForPictures
// Set prefab index
obstacleComponent.PrefabIndex = prefabIndex;
// Randomize properties
obstacleComponent.MoveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed);
// Randomize properties using settings
obstacleComponent.MoveSpeed = Random.Range(
_settings.EndlessDescenderObstacleMinMoveSpeed,
_settings.EndlessDescenderObstacleMaxMoveSpeed);
// Set spawner reference (since FloatingObstacle has this built-in now)
obstacleComponent.SetSpawner(this);
@@ -440,7 +435,7 @@ namespace Minigames.DivingForPictures
onObstacleDestroyed?.Invoke(obstacle);
// Return to pool or destroy
if (useObjectPooling && _obstaclePool != null)
if (_devSettings.ObstacleUseObjectPooling && _obstaclePool != null)
{
Debug.Log($"[ObstacleSpawner] Returning {obstacle.name} to pool");
_obstaclePool.ReturnObstacle(obstacle, prefabIndex);
@@ -457,7 +452,9 @@ namespace Minigames.DivingForPictures
/// </summary>
public void SetSpawnInterval(float interval)
{
spawnInterval = interval;
// This method can no longer directly modify the settings
// Consider implementing a runtime settings override system if needed
Debug.LogWarning("[ObstacleSpawner] SetSpawnInterval no longer modifies settings directly. Settings are now centralized.");
}
/// <summary>
@@ -465,8 +462,9 @@ namespace Minigames.DivingForPictures
/// </summary>
public void SetSpeedRange(float min, float max)
{
minMoveSpeed = min;
maxMoveSpeed = max;
// This method can no longer directly modify the settings
// Consider implementing a runtime settings override system if needed
Debug.LogWarning("[ObstacleSpawner] SetSpeedRange no longer modifies settings directly. Settings are now centralized.");
}
/// <summary>
@@ -534,8 +532,8 @@ namespace Minigames.DivingForPictures
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
// Only draw if screen bounds have been calculated
if (_spawnRangeX > 0f)
// Only draw if screen bounds have been calculated and settings are available
if (_spawnRangeX > 0f && _settings != null)
{
// Draw spawn area using dynamic calculations
Gizmos.color = Color.yellow;
@@ -545,7 +543,7 @@ namespace Minigames.DivingForPictures
// Draw collision radius at spawn point
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(center, spawnCollisionRadius);
Gizmos.DrawWireSphere(center, _settings.EndlessDescenderObstacleSpawnCollisionRadius);
}
}
#endif