IMplement basic Developer Settings
This commit is contained in:
@@ -12,7 +12,7 @@ namespace AppleHills.Editor
|
|||||||
{
|
{
|
||||||
private static PlayerFollowerSettings _playerFollowerSettings;
|
private static PlayerFollowerSettings _playerFollowerSettings;
|
||||||
private static InteractionSettings _interactionSettings;
|
private static InteractionSettings _interactionSettings;
|
||||||
private static MinigameSettings _minigameSettings;
|
private static DivingMinigameSettings _divingMinigameSettings;
|
||||||
|
|
||||||
// Static constructor will be called when Unity loads/reloads scripts
|
// Static constructor will be called when Unity loads/reloads scripts
|
||||||
static EditorSettingsProvider()
|
static EditorSettingsProvider()
|
||||||
@@ -53,7 +53,7 @@ namespace AppleHills.Editor
|
|||||||
{
|
{
|
||||||
_playerFollowerSettings = AssetDatabase.LoadAssetAtPath<PlayerFollowerSettings>("Assets/Settings/PlayerFollowerSettings.asset");
|
_playerFollowerSettings = AssetDatabase.LoadAssetAtPath<PlayerFollowerSettings>("Assets/Settings/PlayerFollowerSettings.asset");
|
||||||
_interactionSettings = AssetDatabase.LoadAssetAtPath<InteractionSettings>("Assets/Settings/InteractionSettings.asset");
|
_interactionSettings = AssetDatabase.LoadAssetAtPath<InteractionSettings>("Assets/Settings/InteractionSettings.asset");
|
||||||
_minigameSettings = AssetDatabase.LoadAssetAtPath<MinigameSettings>("Assets/Settings/MinigameSettings.asset");
|
_divingMinigameSettings = AssetDatabase.LoadAssetAtPath<DivingMinigameSettings>("Assets/Settings/MinigameSettings.asset");
|
||||||
|
|
||||||
// Re-register the delegates in case they were lost
|
// Re-register the delegates in case they were lost
|
||||||
AppleHills.SettingsAccess.SetupEditorProviders(
|
AppleHills.SettingsAccess.SetupEditorProviders(
|
||||||
@@ -88,8 +88,8 @@ namespace AppleHills.Editor
|
|||||||
return _playerFollowerSettings as T;
|
return _playerFollowerSettings as T;
|
||||||
else if (typeof(T) == typeof(InteractionSettings))
|
else if (typeof(T) == typeof(InteractionSettings))
|
||||||
return _interactionSettings as T;
|
return _interactionSettings as T;
|
||||||
else if (typeof(T) == typeof(MinigameSettings))
|
else if (typeof(T) == typeof(DivingMinigameSettings))
|
||||||
return _minigameSettings as T;
|
return _divingMinigameSettings as T;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace AppleHills.Core.Settings.Editor
|
|||||||
// If any settings are missing, create them
|
// If any settings are missing, create them
|
||||||
CreateSettingsIfMissing<PlayerFollowerSettings>("PlayerFollowerSettings");
|
CreateSettingsIfMissing<PlayerFollowerSettings>("PlayerFollowerSettings");
|
||||||
CreateSettingsIfMissing<InteractionSettings>("InteractionSettings");
|
CreateSettingsIfMissing<InteractionSettings>("InteractionSettings");
|
||||||
CreateSettingsIfMissing<MinigameSettings>("MinigameSettings");
|
CreateSettingsIfMissing<DivingMinigameSettings>("MinigameSettings");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
|
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
|
||||||
@@ -112,7 +112,7 @@ namespace AppleHills.Core.Settings.Editor
|
|||||||
DrawSettingsEditor<InteractionSettings>();
|
DrawSettingsEditor<InteractionSettings>();
|
||||||
break;
|
break;
|
||||||
case 2: // Minigames
|
case 2: // Minigames
|
||||||
DrawSettingsEditor<MinigameSettings>();
|
DrawSettingsEditor<DivingMinigameSettings>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ public class GameManager : MonoBehaviour
|
|||||||
|
|
||||||
[Header("Settings Status")]
|
[Header("Settings Status")]
|
||||||
[SerializeField] private bool _settingsLoaded = false;
|
[SerializeField] private bool _settingsLoaded = false;
|
||||||
|
[SerializeField] private bool _developerSettingsLoaded = false;
|
||||||
public bool SettingsLoaded => _settingsLoaded;
|
public bool SettingsLoaded => _settingsLoaded;
|
||||||
|
public bool DeveloperSettingsLoaded => _developerSettingsLoaded;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
@@ -42,8 +44,12 @@ public class GameManager : MonoBehaviour
|
|||||||
// Create settings provider if it doesn't exist
|
// Create settings provider if it doesn't exist
|
||||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||||
|
|
||||||
|
// Create developer settings provider if it doesn't exist
|
||||||
|
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||||||
|
|
||||||
// Load all settings synchronously during Awake
|
// Load all settings synchronously during Awake
|
||||||
InitializeSettings();
|
InitializeSettings();
|
||||||
|
InitializeDeveloperSettings();
|
||||||
|
|
||||||
// DontDestroyOnLoad(gameObject);
|
// DontDestroyOnLoad(gameObject);
|
||||||
}
|
}
|
||||||
@@ -55,7 +61,7 @@ public class GameManager : MonoBehaviour
|
|||||||
// Load settings synchronously
|
// Load settings synchronously
|
||||||
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
||||||
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
|
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
|
||||||
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<MinigameSettings>();
|
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
|
||||||
|
|
||||||
// Register settings with service locator
|
// Register settings with service locator
|
||||||
if (playerSettings != null)
|
if (playerSettings != null)
|
||||||
@@ -80,7 +86,7 @@ public class GameManager : MonoBehaviour
|
|||||||
|
|
||||||
if (minigameSettings != null)
|
if (minigameSettings != null)
|
||||||
{
|
{
|
||||||
ServiceLocator.Register<IMinigameSettings>(minigameSettings);
|
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
|
||||||
Debug.Log("MinigameSettings registered successfully");
|
Debug.Log("MinigameSettings registered successfully");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -100,6 +106,28 @@ public class GameManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check for and initialize developer settings.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeDeveloperSettings()
|
||||||
|
{
|
||||||
|
Debug.Log("Starting developer settings initialization...");
|
||||||
|
|
||||||
|
// Load developer settings
|
||||||
|
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
||||||
|
|
||||||
|
_developerSettingsLoaded = divingDevSettings != null;
|
||||||
|
|
||||||
|
if (_developerSettingsLoaded)
|
||||||
|
{
|
||||||
|
Debug.Log("All developer settings loaded successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Some developer settings failed to load");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnApplicationQuit()
|
void OnApplicationQuit()
|
||||||
{
|
{
|
||||||
_isQuitting = true;
|
_isQuitting = true;
|
||||||
@@ -112,6 +140,26 @@ public class GameManager : MonoBehaviour
|
|||||||
return ServiceLocator.Get<T>();
|
return ServiceLocator.Get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the entire settings object of specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of settings to retrieve</typeparam>
|
||||||
|
/// <returns>The settings object or null if not found</returns>
|
||||||
|
public static T GetSettingsObject<T>() where T : class
|
||||||
|
{
|
||||||
|
return Instance?.GetSettings<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the developer settings object of specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
|
||||||
|
/// <returns>The developer settings object or null if not found</returns>
|
||||||
|
public static T GetDeveloperSettings<T>() where T : BaseDeveloperSettings
|
||||||
|
{
|
||||||
|
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
|
||||||
|
}
|
||||||
|
|
||||||
// PLAYER & FOLLOWER SETTINGS
|
// PLAYER & FOLLOWER SETTINGS
|
||||||
|
|
||||||
// Player settings
|
// Player settings
|
||||||
@@ -178,9 +226,18 @@ public class GameManager : MonoBehaviour
|
|||||||
// MINIGAME SETTINGS
|
// MINIGAME SETTINGS
|
||||||
|
|
||||||
// Endless Descender settings
|
// Endless Descender settings
|
||||||
public float EndlessDescenderLerpSpeed => GetSettings<IMinigameSettings>()?.EndlessDescenderLerpSpeed ?? 12f;
|
public float EndlessDescenderLerpSpeed => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderLerpSpeed ?? 12f;
|
||||||
public float EndlessDescenderMaxOffset => GetSettings<IMinigameSettings>()?.EndlessDescenderMaxOffset ?? 3f;
|
public float EndlessDescenderMaxOffset => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderMaxOffset ?? 3f;
|
||||||
public float EndlessDescenderClampXMin => GetSettings<IMinigameSettings>()?.EndlessDescenderClampXMin ?? -3.5f;
|
public float EndlessDescenderClampXMin => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderClampXMin ?? -3.5f;
|
||||||
public float EndlessDescenderClampXMax => GetSettings<IMinigameSettings>()?.EndlessDescenderClampXMax ?? 3.5f;
|
public float EndlessDescenderClampXMax => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderClampXMax ?? 3.5f;
|
||||||
public float EndlessDescenderSpeedExponent => GetSettings<IMinigameSettings>()?.EndlessDescenderSpeedExponent ?? 2.5f;
|
public float EndlessDescenderSpeedExponent => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderSpeedExponent ?? 2.5f;
|
||||||
|
public float EndlessDescenderTapMaxDistance => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderTapMaxDistance ?? 0.5f;
|
||||||
|
public float EndlessDescenderTapDecelerationRate => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderTapDecelerationRate ?? 5.0f;
|
||||||
|
public int EndlessDescenderInitialTileCount => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderInitialTileCount ?? 3;
|
||||||
|
public float EndlessDescenderTileSpawnBuffer => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderTileSpawnBuffer ?? 1f;
|
||||||
|
public float EndlessDescenderMoveSpeed => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderMoveSpeed ?? 3f;
|
||||||
|
public float EndlessDescenderSpeedUpFactor => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderSpeedUpFactor ?? 0.2f;
|
||||||
|
public float EndlessDescenderSpeedUpInterval => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderSpeedUpInterval ?? 10f;
|
||||||
|
public float EndlessDescenderMaxMoveSpeed => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderMaxMoveSpeed ?? 12f;
|
||||||
|
public float EndlessDescenderVelocityCalculationInterval => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderVelocityCalculationInterval ?? 0.5f;
|
||||||
}
|
}
|
||||||
|
|||||||
19
Assets/Scripts/Core/Settings/BaseDeveloperSettings.cs
Normal file
19
Assets/Scripts/Core/Settings/BaseDeveloperSettings.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AppleHills.Core.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base abstract class for all developer settings.
|
||||||
|
/// Developer settings are intended for technical configuration rather than gameplay/design values.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseDeveloperSettings : ScriptableObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called to validate settings values when they are changed in the inspector.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnValidate()
|
||||||
|
{
|
||||||
|
// Base implementation does nothing, override in derived classes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 50def2e6e95a4830b57f3e1b76a4df51
|
||||||
|
timeCreated: 1758707161
|
||||||
95
Assets/Scripts/Core/Settings/DeveloperSettingsProvider.cs
Normal file
95
Assets/Scripts/Core/Settings/DeveloperSettingsProvider.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AppleHills.Core.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to developer settings for technical configuration rather than gameplay parameters.
|
||||||
|
/// Follows the singleton pattern for global access.
|
||||||
|
/// </summary>
|
||||||
|
public class DeveloperSettingsProvider : MonoBehaviour
|
||||||
|
{
|
||||||
|
private static DeveloperSettingsProvider _instance;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton instance of the provider.
|
||||||
|
/// </summary>
|
||||||
|
public static DeveloperSettingsProvider Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null && Application.isPlaying)
|
||||||
|
{
|
||||||
|
_instance = FindFirstObjectByType<DeveloperSettingsProvider>();
|
||||||
|
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
GameObject go = new GameObject("DeveloperSettingsProvider");
|
||||||
|
_instance = go.AddComponent<DeveloperSettingsProvider>();
|
||||||
|
// Don't destroy between scenes
|
||||||
|
DontDestroyOnLoad(go);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dictionary to cache loaded settings
|
||||||
|
private Dictionary<System.Type, BaseDeveloperSettings> _settingsCache = new Dictionary<System.Type, BaseDeveloperSettings>();
|
||||||
|
|
||||||
|
// Default developer settings stored in the Resources folder
|
||||||
|
[SerializeField] private string _resourcesPath = "Settings/Developer";
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (_instance != null && _instance != this)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_instance = this;
|
||||||
|
DontDestroyOnLoad(gameObject);
|
||||||
|
|
||||||
|
// Initialize settings cache
|
||||||
|
_settingsCache = new Dictionary<System.Type, BaseDeveloperSettings>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or loads developer settings of the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
|
||||||
|
/// <returns>The settings instance or null if not found</returns>
|
||||||
|
public T GetSettings<T>() where T : BaseDeveloperSettings
|
||||||
|
{
|
||||||
|
System.Type type = typeof(T);
|
||||||
|
|
||||||
|
// Return from cache if available
|
||||||
|
if (_settingsCache.TryGetValue(type, out BaseDeveloperSettings cachedSettings))
|
||||||
|
{
|
||||||
|
return cachedSettings as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from Resources if not cached
|
||||||
|
T settings = Resources.Load<T>($"{_resourcesPath}/{type.Name}");
|
||||||
|
|
||||||
|
if (settings != null)
|
||||||
|
{
|
||||||
|
_settingsCache[type] = settings;
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogWarning($"Developer settings of type {type.Name} not found in Resources/{_resourcesPath}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the settings cache, forcing settings to be reloaded.
|
||||||
|
/// </summary>
|
||||||
|
public void ClearCache()
|
||||||
|
{
|
||||||
|
_settingsCache.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f9945aa4a563434e973ab49176259150
|
||||||
|
timeCreated: 1758707186
|
||||||
127
Assets/Scripts/Core/Settings/DivingDeveloperSettings.cs
Normal file
127
Assets/Scripts/Core/Settings/DivingDeveloperSettings.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AppleHills.Core.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Developer settings for the diving minigame technical configuration.
|
||||||
|
/// These settings are separate from gameplay/design settings and focus on technical implementation details.
|
||||||
|
/// </summary>
|
||||||
|
[CreateAssetMenu(fileName = "DivingDeveloperSettings", menuName = "AppleHills/Developer Settings/Diving", order = 1)]
|
||||||
|
public class DivingDeveloperSettings : BaseDeveloperSettings
|
||||||
|
{
|
||||||
|
[Header("Bubble System")]
|
||||||
|
[Tooltip("Object pooling enabled for bubbles")]
|
||||||
|
[SerializeField] private bool bubbleUseObjectPooling = true;
|
||||||
|
|
||||||
|
[Tooltip("Initial number of bubbles to pre-allocate in pool")]
|
||||||
|
[SerializeField] private int bubbleInitialPoolSize = 10;
|
||||||
|
|
||||||
|
[Tooltip("Maximum number of bubbles allowed in pool")]
|
||||||
|
[SerializeField] private int bubbleMaxPoolSize = 30;
|
||||||
|
|
||||||
|
[Tooltip("Default spawn interval for bubbles in seconds")]
|
||||||
|
[SerializeField] private float bubbleSpawnInterval = 0.3f;
|
||||||
|
|
||||||
|
[Tooltip("Range of possible bubble movement speeds (min, max)")]
|
||||||
|
[SerializeField] private Vector2 bubbleSpeedRange = new Vector2(0.5f, 2f);
|
||||||
|
|
||||||
|
[Tooltip("Range of possible bubble scale factors (min, max)")]
|
||||||
|
[SerializeField] private Vector2 bubbleScaleRange = new Vector2(0.3f, 0.7f);
|
||||||
|
|
||||||
|
[Tooltip("Range of possible bubble wobble speeds (min, max)")]
|
||||||
|
[SerializeField] private Vector2 bubbleWobbleSpeedRange = new Vector2(1f, 3f);
|
||||||
|
|
||||||
|
[Tooltip("Range of possible bubble wobble amounts (min, max)")]
|
||||||
|
[SerializeField] private Vector2 bubbleWobbleAmountRange = new Vector2(0.05f, 0.15f);
|
||||||
|
|
||||||
|
[Tooltip("Minimum X position for bubble spawning")]
|
||||||
|
[SerializeField] private float bubbleSpawnXMin = -3.5f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum X position for bubble spawning")]
|
||||||
|
[SerializeField] private float bubbleSpawnXMax = 3.5f;
|
||||||
|
|
||||||
|
[Tooltip("Y position for bubble spawning")]
|
||||||
|
[SerializeField] private float bubbleSpawnY = -5f;
|
||||||
|
|
||||||
|
[Tooltip("Minimum scale factor during wobble animation")]
|
||||||
|
[SerializeField] private float bubbleWobbleMinScale = 0.2f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum scale factor during wobble animation")]
|
||||||
|
[SerializeField] private float bubbleWobbleMaxScale = 1.2f;
|
||||||
|
|
||||||
|
[Tooltip("Factor to multiply bubble speed by when surfacing")]
|
||||||
|
[SerializeField] private float bubbleSurfacingSpeedFactor = 0.5f;
|
||||||
|
|
||||||
|
[Header("Obstacle System")]
|
||||||
|
[Tooltip("Layer for obstacles to be placed on")]
|
||||||
|
[SerializeField] private int obstacleLayer = 9;
|
||||||
|
|
||||||
|
[Tooltip("Layer mask for tile collision detection during obstacle spawn validation")]
|
||||||
|
[SerializeField] private LayerMask obstacleTileLayerMask = -1;
|
||||||
|
|
||||||
|
[Tooltip("Whether to use object pooling for obstacles")]
|
||||||
|
[SerializeField] private bool obstacleUseObjectPooling = true;
|
||||||
|
|
||||||
|
[Tooltip("Maximum objects per prefab type in obstacle pool")]
|
||||||
|
[SerializeField] private int obstacleMaxPerPrefabPoolSize = 3;
|
||||||
|
|
||||||
|
[Tooltip("Total maximum size of obstacle pool across all prefab types")]
|
||||||
|
[SerializeField] private int obstacleTotalMaxPoolSize = 15;
|
||||||
|
|
||||||
|
// Bubble properties access
|
||||||
|
public bool BubbleUseObjectPooling => bubbleUseObjectPooling;
|
||||||
|
public int BubbleInitialPoolSize => bubbleInitialPoolSize;
|
||||||
|
public int BubbleMaxPoolSize => bubbleMaxPoolSize;
|
||||||
|
public float BubbleSpawnInterval => bubbleSpawnInterval;
|
||||||
|
public Vector2 BubbleSpeedRange => bubbleSpeedRange;
|
||||||
|
public Vector2 BubbleScaleRange => bubbleScaleRange;
|
||||||
|
public Vector2 BubbleWobbleSpeedRange => bubbleWobbleSpeedRange;
|
||||||
|
public Vector2 BubbleWobbleAmountRange => bubbleWobbleAmountRange;
|
||||||
|
public float BubbleSpawnXMin => bubbleSpawnXMin;
|
||||||
|
public float BubbleSpawnXMax => bubbleSpawnXMax;
|
||||||
|
public float BubbleSpawnY => bubbleSpawnY;
|
||||||
|
public float BubbleWobbleMinScale => bubbleWobbleMinScale;
|
||||||
|
public float BubbleWobbleMaxScale => bubbleWobbleMaxScale;
|
||||||
|
public float BubbleSurfacingSpeedFactor => bubbleSurfacingSpeedFactor;
|
||||||
|
|
||||||
|
// Obstacle properties access
|
||||||
|
public int ObstacleLayer => obstacleLayer;
|
||||||
|
public LayerMask ObstacleTileLayerMask => obstacleTileLayerMask;
|
||||||
|
public bool ObstacleUseObjectPooling => obstacleUseObjectPooling;
|
||||||
|
public int ObstacleMaxPerPrefabPoolSize => obstacleMaxPerPrefabPoolSize;
|
||||||
|
public int ObstacleTotalMaxPoolSize => obstacleTotalMaxPoolSize;
|
||||||
|
|
||||||
|
public override void OnValidate()
|
||||||
|
{
|
||||||
|
base.OnValidate();
|
||||||
|
|
||||||
|
// Validate bubble settings
|
||||||
|
bubbleInitialPoolSize = Mathf.Max(1, bubbleInitialPoolSize);
|
||||||
|
bubbleMaxPoolSize = Mathf.Max(bubbleInitialPoolSize, bubbleMaxPoolSize);
|
||||||
|
bubbleSpawnInterval = Mathf.Max(0.05f, bubbleSpawnInterval);
|
||||||
|
bubbleSpeedRange = new Vector2(
|
||||||
|
Mathf.Max(0.1f, bubbleSpeedRange.x),
|
||||||
|
Mathf.Max(bubbleSpeedRange.x, bubbleSpeedRange.y)
|
||||||
|
);
|
||||||
|
bubbleScaleRange = new Vector2(
|
||||||
|
Mathf.Max(0.1f, bubbleScaleRange.x),
|
||||||
|
Mathf.Max(bubbleScaleRange.x, bubbleScaleRange.y)
|
||||||
|
);
|
||||||
|
bubbleWobbleSpeedRange = new Vector2(
|
||||||
|
Mathf.Max(0.1f, bubbleWobbleSpeedRange.x),
|
||||||
|
Mathf.Max(bubbleWobbleSpeedRange.x, bubbleWobbleSpeedRange.y)
|
||||||
|
);
|
||||||
|
bubbleWobbleAmountRange = new Vector2(
|
||||||
|
Mathf.Max(0.01f, bubbleWobbleAmountRange.x),
|
||||||
|
Mathf.Max(bubbleWobbleAmountRange.x, bubbleWobbleAmountRange.y)
|
||||||
|
);
|
||||||
|
bubbleWobbleMinScale = Mathf.Max(0.01f, bubbleWobbleMinScale);
|
||||||
|
bubbleWobbleMaxScale = Mathf.Max(bubbleWobbleMinScale, bubbleWobbleMaxScale);
|
||||||
|
bubbleSurfacingSpeedFactor = Mathf.Max(0.01f, bubbleSurfacingSpeedFactor);
|
||||||
|
|
||||||
|
// Validate obstacle settings
|
||||||
|
obstacleMaxPerPrefabPoolSize = Mathf.Max(1, obstacleMaxPerPrefabPoolSize);
|
||||||
|
obstacleTotalMaxPoolSize = Mathf.Max(obstacleMaxPerPrefabPoolSize, obstacleTotalMaxPoolSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 033961b12e7b4289838d554c2264bacd
|
||||||
|
timeCreated: 1758707215
|
||||||
210
Assets/Scripts/Core/Settings/DivingMinigameSettings.cs
Normal file
210
Assets/Scripts/Core/Settings/DivingMinigameSettings.cs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AppleHills.Core.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Settings related to minigames
|
||||||
|
/// </summary>
|
||||||
|
[CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)]
|
||||||
|
public class DivingMinigameSettings : BaseSettings, IDivingMinigameSettings
|
||||||
|
{
|
||||||
|
[Header("Endless Descender - Basic Movement")]
|
||||||
|
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
|
||||||
|
[SerializeField] private float endlessDescenderLerpSpeed = 12f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum horizontal offset allowed between character and finger position")]
|
||||||
|
[SerializeField] private float endlessDescenderMaxOffset = 3f;
|
||||||
|
|
||||||
|
[Tooltip("Minimum allowed X position for endless descender movement")]
|
||||||
|
[SerializeField] private float endlessDescenderClampXMin = -3.5f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum allowed X position for endless descender movement")]
|
||||||
|
[SerializeField] private float endlessDescenderClampXMax = 3.5f;
|
||||||
|
|
||||||
|
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
|
||||||
|
[SerializeField] private float endlessDescenderSpeedExponent = 2.5f;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Player Movement")]
|
||||||
|
[Tooltip("Maximum distance the player can move from a single tap")]
|
||||||
|
[SerializeField] private float endlessDescenderTapMaxDistance = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("How quickly the tap impulse fades (higher = faster stop)")]
|
||||||
|
[SerializeField] private float endlessDescenderTapDecelerationRate = 5.0f;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Monster Spawning")]
|
||||||
|
[Tooltip("Base chance (0-1) of spawning a monster on each tile")]
|
||||||
|
[SerializeField] private float endlessDescenderBaseSpawnProbability = 0.2f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum chance (0-1) of spawning a monster")]
|
||||||
|
[SerializeField] private float endlessDescenderMaxSpawnProbability = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("How fast the probability increases per second")]
|
||||||
|
[SerializeField] private float endlessDescenderProbabilityIncreaseRate = 0.01f;
|
||||||
|
|
||||||
|
[Tooltip("Force a spawn after this many seconds without spawns")]
|
||||||
|
[SerializeField] private float endlessDescenderGuaranteedSpawnTime = 30f;
|
||||||
|
|
||||||
|
[Tooltip("Minimum time between monster spawns")]
|
||||||
|
[SerializeField] private float endlessDescenderSpawnCooldown = 5f;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Scoring")]
|
||||||
|
[Tooltip("Base points for taking a picture")]
|
||||||
|
[SerializeField] private int endlessDescenderBasePoints = 100;
|
||||||
|
|
||||||
|
[Tooltip("Additional points per depth unit")]
|
||||||
|
[SerializeField] private int endlessDescenderDepthMultiplier = 10;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Surfacing")]
|
||||||
|
[Tooltip("Duration in seconds for speed transition when surfacing")]
|
||||||
|
[SerializeField] private float endlessDescenderSpeedTransitionDuration = 2.0f;
|
||||||
|
|
||||||
|
[Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
|
||||||
|
[SerializeField] private float endlessDescenderSurfacingSpeedFactor = 3.0f;
|
||||||
|
|
||||||
|
[Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
|
||||||
|
[SerializeField] private float endlessDescenderSurfacingSpawnDelay = 5.0f;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Tile Generation")]
|
||||||
|
[Tooltip("Initial number of tiles to create at start")]
|
||||||
|
[SerializeField] private int endlessDescenderInitialTileCount = 3;
|
||||||
|
|
||||||
|
[Tooltip("Buffer distance for spawning new tiles")]
|
||||||
|
[SerializeField] private float endlessDescenderTileSpawnBuffer = 1f;
|
||||||
|
|
||||||
|
[Tooltip("Base movement speed for tiles")]
|
||||||
|
[SerializeField] private float endlessDescenderMoveSpeed = 3f;
|
||||||
|
|
||||||
|
[Tooltip("Factor to increase speed by each interval")]
|
||||||
|
[SerializeField] private float endlessDescenderSpeedUpFactor = 0.2f;
|
||||||
|
|
||||||
|
[Tooltip("Time interval between speed increases (seconds)")]
|
||||||
|
[SerializeField] private float endlessDescenderSpeedUpInterval = 10f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum movement speed allowed")]
|
||||||
|
[SerializeField] private float endlessDescenderMaxMoveSpeed = 12f;
|
||||||
|
|
||||||
|
[Tooltip("Interval for velocity calculations (seconds)")]
|
||||||
|
[SerializeField] private float endlessDescenderVelocityCalculationInterval = 0.5f;
|
||||||
|
|
||||||
|
[Header("Endless Descender - Obstacles")]
|
||||||
|
[Tooltip("Time interval between obstacle spawn attempts (in seconds)")]
|
||||||
|
[SerializeField] private float endlessDescenderObstacleSpawnInterval = 2f;
|
||||||
|
|
||||||
|
[Tooltip("Random variation in obstacle spawn timing (+/- seconds)")]
|
||||||
|
[SerializeField] private float endlessDescenderObstacleSpawnIntervalVariation = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum number of obstacle spawn position attempts before skipping")]
|
||||||
|
[SerializeField] private int endlessDescenderObstacleMaxSpawnAttempts = 10;
|
||||||
|
|
||||||
|
[Tooltip("Radius around obstacle spawn point to check for tile collisions")]
|
||||||
|
[SerializeField] private float endlessDescenderObstacleSpawnCollisionRadius = 1f;
|
||||||
|
|
||||||
|
[Tooltip("Minimum movement speed for spawned obstacles")]
|
||||||
|
[SerializeField] private float endlessDescenderObstacleMinMoveSpeed = 1f;
|
||||||
|
|
||||||
|
[Tooltip("Maximum movement speed for spawned obstacles")]
|
||||||
|
[SerializeField] private float endlessDescenderObstacleMaxMoveSpeed = 4f;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Basic Movement
|
||||||
|
public float EndlessDescenderLerpSpeed => endlessDescenderLerpSpeed;
|
||||||
|
public float EndlessDescenderMaxOffset => endlessDescenderMaxOffset;
|
||||||
|
public float EndlessDescenderClampXMin => endlessDescenderClampXMin;
|
||||||
|
public float EndlessDescenderClampXMax => endlessDescenderClampXMax;
|
||||||
|
public float EndlessDescenderSpeedExponent => endlessDescenderSpeedExponent;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Player Movement
|
||||||
|
public float EndlessDescenderTapMaxDistance => endlessDescenderTapMaxDistance;
|
||||||
|
public float EndlessDescenderTapDecelerationRate => endlessDescenderTapDecelerationRate;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Monster Spawning
|
||||||
|
public float EndlessDescenderBaseSpawnProbability => endlessDescenderBaseSpawnProbability;
|
||||||
|
public float EndlessDescenderMaxSpawnProbability => endlessDescenderMaxSpawnProbability;
|
||||||
|
public float EndlessDescenderProbabilityIncreaseRate => endlessDescenderProbabilityIncreaseRate;
|
||||||
|
public float EndlessDescenderGuaranteedSpawnTime => endlessDescenderGuaranteedSpawnTime;
|
||||||
|
public float EndlessDescenderSpawnCooldown => endlessDescenderSpawnCooldown;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Scoring
|
||||||
|
public int EndlessDescenderBasePoints => endlessDescenderBasePoints;
|
||||||
|
public int EndlessDescenderDepthMultiplier => endlessDescenderDepthMultiplier;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Surfacing
|
||||||
|
public float EndlessDescenderSpeedTransitionDuration => endlessDescenderSpeedTransitionDuration;
|
||||||
|
public float EndlessDescenderSurfacingSpeedFactor => endlessDescenderSurfacingSpeedFactor;
|
||||||
|
public float EndlessDescenderSurfacingSpawnDelay => endlessDescenderSurfacingSpawnDelay;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Tile Generation
|
||||||
|
public int EndlessDescenderInitialTileCount => endlessDescenderInitialTileCount;
|
||||||
|
public float EndlessDescenderTileSpawnBuffer => endlessDescenderTileSpawnBuffer;
|
||||||
|
public float EndlessDescenderMoveSpeed => endlessDescenderMoveSpeed;
|
||||||
|
public float EndlessDescenderSpeedUpFactor => endlessDescenderSpeedUpFactor;
|
||||||
|
public float EndlessDescenderSpeedUpInterval => endlessDescenderSpeedUpInterval;
|
||||||
|
public float EndlessDescenderMaxMoveSpeed => endlessDescenderMaxMoveSpeed;
|
||||||
|
public float EndlessDescenderVelocityCalculationInterval => endlessDescenderVelocityCalculationInterval;
|
||||||
|
|
||||||
|
// IMinigameSettings implementation - Obstacles
|
||||||
|
public float EndlessDescenderObstacleSpawnInterval => endlessDescenderObstacleSpawnInterval;
|
||||||
|
public float EndlessDescenderObstacleSpawnIntervalVariation => endlessDescenderObstacleSpawnIntervalVariation;
|
||||||
|
public int EndlessDescenderObstacleMaxSpawnAttempts => endlessDescenderObstacleMaxSpawnAttempts;
|
||||||
|
public float EndlessDescenderObstacleSpawnCollisionRadius => endlessDescenderObstacleSpawnCollisionRadius;
|
||||||
|
public float EndlessDescenderObstacleMinMoveSpeed => endlessDescenderObstacleMinMoveSpeed;
|
||||||
|
public float EndlessDescenderObstacleMaxMoveSpeed => endlessDescenderObstacleMaxMoveSpeed;
|
||||||
|
|
||||||
|
public override void OnValidate()
|
||||||
|
{
|
||||||
|
base.OnValidate();
|
||||||
|
|
||||||
|
// Validate basic movement values
|
||||||
|
endlessDescenderLerpSpeed = Mathf.Max(0.1f, endlessDescenderLerpSpeed);
|
||||||
|
endlessDescenderMaxOffset = Mathf.Max(0.1f, endlessDescenderMaxOffset);
|
||||||
|
endlessDescenderSpeedExponent = Mathf.Max(0.1f, endlessDescenderSpeedExponent);
|
||||||
|
|
||||||
|
// Ensure min is less than max for clamping
|
||||||
|
if (endlessDescenderClampXMin >= endlessDescenderClampXMax)
|
||||||
|
{
|
||||||
|
endlessDescenderClampXMin = endlessDescenderClampXMax - 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate player movement
|
||||||
|
endlessDescenderTapMaxDistance = Mathf.Max(0.01f, endlessDescenderTapMaxDistance);
|
||||||
|
endlessDescenderTapDecelerationRate = Mathf.Max(0.1f, endlessDescenderTapDecelerationRate);
|
||||||
|
|
||||||
|
// Validate probability values
|
||||||
|
endlessDescenderBaseSpawnProbability = Mathf.Clamp01(endlessDescenderBaseSpawnProbability);
|
||||||
|
endlessDescenderMaxSpawnProbability = Mathf.Clamp01(endlessDescenderMaxSpawnProbability);
|
||||||
|
endlessDescenderProbabilityIncreaseRate = Mathf.Max(0f, endlessDescenderProbabilityIncreaseRate);
|
||||||
|
|
||||||
|
// Ensure max probability is at least base probability
|
||||||
|
if (endlessDescenderMaxSpawnProbability < endlessDescenderBaseSpawnProbability)
|
||||||
|
{
|
||||||
|
endlessDescenderMaxSpawnProbability = endlessDescenderBaseSpawnProbability;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate time values
|
||||||
|
endlessDescenderGuaranteedSpawnTime = Mathf.Max(0.1f, endlessDescenderGuaranteedSpawnTime);
|
||||||
|
endlessDescenderSpawnCooldown = Mathf.Max(0.1f, endlessDescenderSpawnCooldown);
|
||||||
|
endlessDescenderSpeedTransitionDuration = Mathf.Max(0.1f, endlessDescenderSpeedTransitionDuration);
|
||||||
|
endlessDescenderSurfacingSpawnDelay = Mathf.Max(0f, endlessDescenderSurfacingSpawnDelay);
|
||||||
|
|
||||||
|
// Validate scoring
|
||||||
|
endlessDescenderBasePoints = Mathf.Max(0, endlessDescenderBasePoints);
|
||||||
|
endlessDescenderDepthMultiplier = Mathf.Max(0, endlessDescenderDepthMultiplier);
|
||||||
|
|
||||||
|
// Validate tile generation
|
||||||
|
endlessDescenderInitialTileCount = Mathf.Max(1, endlessDescenderInitialTileCount);
|
||||||
|
endlessDescenderTileSpawnBuffer = Mathf.Max(0f, endlessDescenderTileSpawnBuffer);
|
||||||
|
endlessDescenderMoveSpeed = Mathf.Max(0.1f, endlessDescenderMoveSpeed);
|
||||||
|
endlessDescenderSpeedUpFactor = Mathf.Max(0f, endlessDescenderSpeedUpFactor);
|
||||||
|
endlessDescenderSpeedUpInterval = Mathf.Max(0.1f, endlessDescenderSpeedUpInterval);
|
||||||
|
endlessDescenderMaxMoveSpeed = Mathf.Max(endlessDescenderMoveSpeed, endlessDescenderMaxMoveSpeed);
|
||||||
|
endlessDescenderVelocityCalculationInterval = Mathf.Max(0.01f, endlessDescenderVelocityCalculationInterval);
|
||||||
|
|
||||||
|
// Validate obstacle values
|
||||||
|
endlessDescenderObstacleSpawnInterval = Mathf.Max(0.1f, endlessDescenderObstacleSpawnInterval);
|
||||||
|
endlessDescenderObstacleSpawnIntervalVariation = Mathf.Max(0f, endlessDescenderObstacleSpawnIntervalVariation);
|
||||||
|
endlessDescenderObstacleMaxSpawnAttempts = Mathf.Max(1, endlessDescenderObstacleMaxSpawnAttempts);
|
||||||
|
endlessDescenderObstacleSpawnCollisionRadius = Mathf.Max(0.1f, endlessDescenderObstacleSpawnCollisionRadius);
|
||||||
|
endlessDescenderObstacleMinMoveSpeed = Mathf.Max(0.1f, endlessDescenderObstacleMinMoveSpeed);
|
||||||
|
endlessDescenderObstacleMaxMoveSpeed = Mathf.Max(endlessDescenderObstacleMinMoveSpeed, endlessDescenderObstacleMaxMoveSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AppleHills.Core.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Settings related to minigames
|
|
||||||
/// </summary>
|
|
||||||
[CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)]
|
|
||||||
public class MinigameSettings : BaseSettings, IMinigameSettings
|
|
||||||
{
|
|
||||||
[Header("Endless Descender Settings")]
|
|
||||||
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
|
|
||||||
[SerializeField] private float endlessDescenderLerpSpeed = 12f;
|
|
||||||
|
|
||||||
[Tooltip("Maximum horizontal offset allowed between character and finger position")]
|
|
||||||
[SerializeField] private float endlessDescenderMaxOffset = 3f;
|
|
||||||
|
|
||||||
[Tooltip("Minimum allowed X position for endless descender movement")]
|
|
||||||
[SerializeField] private float endlessDescenderClampXMin = -3.5f;
|
|
||||||
|
|
||||||
[Tooltip("Maximum allowed X position for endless descender movement")]
|
|
||||||
[SerializeField] private float endlessDescenderClampXMax = 3.5f;
|
|
||||||
|
|
||||||
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
|
|
||||||
[SerializeField] private float endlessDescenderSpeedExponent = 2.5f;
|
|
||||||
|
|
||||||
// IMinigameSettings implementation
|
|
||||||
public float EndlessDescenderLerpSpeed => endlessDescenderLerpSpeed;
|
|
||||||
public float EndlessDescenderMaxOffset => endlessDescenderMaxOffset;
|
|
||||||
public float EndlessDescenderClampXMin => endlessDescenderClampXMin;
|
|
||||||
public float EndlessDescenderClampXMax => endlessDescenderClampXMax;
|
|
||||||
public float EndlessDescenderSpeedExponent => endlessDescenderSpeedExponent;
|
|
||||||
|
|
||||||
public override void OnValidate()
|
|
||||||
{
|
|
||||||
base.OnValidate();
|
|
||||||
// Validate values
|
|
||||||
endlessDescenderLerpSpeed = Mathf.Max(0.1f, endlessDescenderLerpSpeed);
|
|
||||||
endlessDescenderMaxOffset = Mathf.Max(0.1f, endlessDescenderMaxOffset);
|
|
||||||
endlessDescenderSpeedExponent = Mathf.Max(0.1f, endlessDescenderSpeedExponent);
|
|
||||||
|
|
||||||
// Ensure min is less than max
|
|
||||||
if (endlessDescenderClampXMin >= endlessDescenderClampXMax)
|
|
||||||
{
|
|
||||||
endlessDescenderClampXMin = endlessDescenderClampXMax - 0.1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -43,13 +43,50 @@ namespace AppleHills.Core.Settings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for minigame settings
|
/// Interface for minigame settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMinigameSettings
|
public interface IDivingMinigameSettings
|
||||||
{
|
{
|
||||||
// Endless Descender settings
|
// Endless Descender settings - Basic Movement
|
||||||
float EndlessDescenderLerpSpeed { get; }
|
float EndlessDescenderLerpSpeed { get; }
|
||||||
float EndlessDescenderMaxOffset { get; }
|
float EndlessDescenderMaxOffset { get; }
|
||||||
float EndlessDescenderClampXMin { get; }
|
float EndlessDescenderClampXMin { get; }
|
||||||
float EndlessDescenderClampXMax { get; }
|
float EndlessDescenderClampXMax { get; }
|
||||||
float EndlessDescenderSpeedExponent { get; }
|
float EndlessDescenderSpeedExponent { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Player Movement
|
||||||
|
float EndlessDescenderTapMaxDistance { get; }
|
||||||
|
float EndlessDescenderTapDecelerationRate { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Monster Spawning
|
||||||
|
float EndlessDescenderBaseSpawnProbability { get; }
|
||||||
|
float EndlessDescenderMaxSpawnProbability { get; }
|
||||||
|
float EndlessDescenderProbabilityIncreaseRate { get; }
|
||||||
|
float EndlessDescenderGuaranteedSpawnTime { get; }
|
||||||
|
float EndlessDescenderSpawnCooldown { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Scoring
|
||||||
|
int EndlessDescenderBasePoints { get; }
|
||||||
|
int EndlessDescenderDepthMultiplier { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Surfacing
|
||||||
|
float EndlessDescenderSpeedTransitionDuration { get; }
|
||||||
|
float EndlessDescenderSurfacingSpeedFactor { get; }
|
||||||
|
float EndlessDescenderSurfacingSpawnDelay { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Tile Generation
|
||||||
|
int EndlessDescenderInitialTileCount { get; }
|
||||||
|
float EndlessDescenderTileSpawnBuffer { get; }
|
||||||
|
float EndlessDescenderMoveSpeed { get; }
|
||||||
|
float EndlessDescenderSpeedUpFactor { get; }
|
||||||
|
float EndlessDescenderSpeedUpInterval { get; }
|
||||||
|
float EndlessDescenderMaxMoveSpeed { get; }
|
||||||
|
float EndlessDescenderVelocityCalculationInterval { get; }
|
||||||
|
|
||||||
|
// Endless Descender - Obstacles
|
||||||
|
float EndlessDescenderObstacleSpawnInterval { get; }
|
||||||
|
float EndlessDescenderObstacleSpawnIntervalVariation { get; }
|
||||||
|
int EndlessDescenderObstacleMaxSpawnAttempts { get; }
|
||||||
|
float EndlessDescenderObstacleSpawnCollisionRadius { get; }
|
||||||
|
float EndlessDescenderObstacleMinMoveSpeed { get; }
|
||||||
|
float EndlessDescenderObstacleMaxMoveSpeed { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Pooling;
|
using Pooling;
|
||||||
|
using AppleHills.Core.Settings;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -10,25 +11,9 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
public Bubble bubblePrefab;
|
public Bubble bubblePrefab;
|
||||||
public Sprite[] bubbleSprites; // Assign in inspector
|
public Sprite[] bubbleSprites; // Assign in inspector
|
||||||
public float spawnInterval = 0.3f;
|
|
||||||
public Vector2 speedRange = new Vector2(0.5f, 2f);
|
|
||||||
public Vector2 scaleRange = new Vector2(0.3f, 0.7f);
|
|
||||||
public Vector2 wobbleSpeedRange = new Vector2(1f, 3f);
|
|
||||||
public Vector2 wobbleAmountRange = new Vector2(0.05f, 0.15f);
|
|
||||||
public float spawnXMin = -3.5f;
|
|
||||||
public float spawnXMax = 3.5f;
|
|
||||||
public float spawnY = -5f;
|
|
||||||
public float wobbleMinScale = 0.2f;
|
|
||||||
public float wobbleMaxScale = 1.2f;
|
|
||||||
|
|
||||||
[Header("Object Pooling")]
|
private DivingDeveloperSettings _devSettings;
|
||||||
public bool useObjectPooling = true;
|
private IDivingMinigameSettings _gameSettings;
|
||||||
public int initialPoolSize = 10;
|
|
||||||
public int maxPoolSize = 30;
|
|
||||||
|
|
||||||
[Header("Surfacing Settings")]
|
|
||||||
[Tooltip("Factor to multiply bubble speed by when surfacing (0.5 = half speed)")]
|
|
||||||
[SerializeField] private float surfacingSpeedFactor = 0.5f;
|
|
||||||
|
|
||||||
private float _timer;
|
private float _timer;
|
||||||
private float _nextSpawnInterval;
|
private float _nextSpawnInterval;
|
||||||
@@ -40,14 +25,24 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
_mainCamera = Camera.main;
|
_mainCamera = Camera.main;
|
||||||
|
|
||||||
if (useObjectPooling)
|
// Get developer settings and game settings
|
||||||
|
_devSettings = GameManager.GetDeveloperSettings<DivingDeveloperSettings>();
|
||||||
|
_gameSettings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||||
|
|
||||||
|
if (_devSettings == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[BubbleSpawner] Failed to load developer settings!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_devSettings.BubbleUseObjectPooling)
|
||||||
{
|
{
|
||||||
// Create the bubble pool
|
// Create the bubble pool
|
||||||
GameObject poolGO = new GameObject("BubblePool");
|
GameObject poolGO = new GameObject("BubblePool");
|
||||||
poolGO.transform.SetParent(transform);
|
poolGO.transform.SetParent(transform);
|
||||||
_bubblePool = poolGO.AddComponent<BubblePool>();
|
_bubblePool = poolGO.AddComponent<BubblePool>();
|
||||||
_bubblePool.initialPoolSize = initialPoolSize;
|
_bubblePool.initialPoolSize = _devSettings.BubbleInitialPoolSize;
|
||||||
_bubblePool.maxPoolSize = maxPoolSize;
|
_bubblePool.maxPoolSize = _devSettings.BubbleMaxPoolSize;
|
||||||
_bubblePool.Initialize(bubblePrefab);
|
_bubblePool.Initialize(bubblePrefab);
|
||||||
|
|
||||||
// Periodically check for pool statistics in debug builds
|
// Periodically check for pool statistics in debug builds
|
||||||
@@ -80,7 +75,7 @@ namespace Minigames.DivingForPictures
|
|||||||
/// <returns>Randomized interval in seconds.</returns>
|
/// <returns>Randomized interval in seconds.</returns>
|
||||||
float GetRandomizedInterval()
|
float GetRandomizedInterval()
|
||||||
{
|
{
|
||||||
return spawnInterval * Random.Range(0.8f, 1.2f);
|
return _devSettings.BubbleSpawnInterval * Random.Range(0.8f, 1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -88,11 +83,11 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void SpawnBubble()
|
void SpawnBubble()
|
||||||
{
|
{
|
||||||
float x = Random.Range(spawnXMin, spawnXMax);
|
float x = Random.Range(_devSettings.BubbleSpawnXMin, _devSettings.BubbleSpawnXMax);
|
||||||
Vector3 spawnPos = new Vector3(x, spawnY, 0f);
|
Vector3 spawnPos = new Vector3(x, _devSettings.BubbleSpawnY, 0f);
|
||||||
|
|
||||||
Bubble bubble;
|
Bubble bubble;
|
||||||
if (useObjectPooling && _bubblePool != null)
|
if (_devSettings.BubbleUseObjectPooling && _bubblePool != null)
|
||||||
{
|
{
|
||||||
bubble = _bubblePool.GetBubble();
|
bubble = _bubblePool.GetBubble();
|
||||||
bubble.transform.position = spawnPos;
|
bubble.transform.position = spawnPos;
|
||||||
@@ -103,25 +98,25 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Randomize bubble properties
|
// Randomize bubble properties
|
||||||
float baseSpeed = Random.Range(speedRange.x, speedRange.y);
|
float baseSpeed = Random.Range(_devSettings.BubbleSpeedRange.x, _devSettings.BubbleSpeedRange.y);
|
||||||
|
|
||||||
// Apply surfacing speed reduction if needed
|
// Apply surfacing speed reduction if needed
|
||||||
if (_isSurfacing)
|
if (_isSurfacing)
|
||||||
{
|
{
|
||||||
bubble.speed = baseSpeed * surfacingSpeedFactor;
|
bubble.speed = baseSpeed * _devSettings.BubbleSurfacingSpeedFactor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bubble.speed = baseSpeed;
|
bubble.speed = baseSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
|
bubble.wobbleSpeed = Random.Range(_devSettings.BubbleWobbleSpeedRange.x, _devSettings.BubbleWobbleSpeedRange.y);
|
||||||
|
|
||||||
// Set base scale (initial size) for the bubble
|
// Set base scale (initial size) for the bubble
|
||||||
float baseScale = Random.Range(scaleRange.x, scaleRange.y);
|
float baseScale = Random.Range(_devSettings.BubbleScaleRange.x, _devSettings.BubbleScaleRange.y);
|
||||||
bubble.SetBaseScale(baseScale);
|
bubble.SetBaseScale(baseScale);
|
||||||
|
|
||||||
// Assign random sprite to BubbleSprite (fixed naming from BottleSprite)
|
// Assign random sprite to BubbleSprite
|
||||||
if (bubbleSprites != null && bubbleSprites.Length > 0)
|
if (bubbleSprites != null && bubbleSprites.Length > 0)
|
||||||
{
|
{
|
||||||
Sprite randomSprite = bubbleSprites[Random.Range(0, bubbleSprites.Length)];
|
Sprite randomSprite = bubbleSprites[Random.Range(0, bubbleSprites.Length)];
|
||||||
@@ -132,7 +127,7 @@ namespace Minigames.DivingForPictures
|
|||||||
bubble.transform.rotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f));
|
bubble.transform.rotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f));
|
||||||
|
|
||||||
// Pass min/max scale for wobble clamping
|
// Pass min/max scale for wobble clamping
|
||||||
bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
|
bubble.SetWobbleScaleLimits(_devSettings.BubbleWobbleMinScale, _devSettings.BubbleWobbleMaxScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -148,10 +143,10 @@ namespace Minigames.DivingForPictures
|
|||||||
Bubble[] activeBubbles = FindObjectsByType<Bubble>(FindObjectsSortMode.None);
|
Bubble[] activeBubbles = FindObjectsByType<Bubble>(FindObjectsSortMode.None);
|
||||||
foreach (Bubble bubble in activeBubbles)
|
foreach (Bubble bubble in activeBubbles)
|
||||||
{
|
{
|
||||||
bubble.speed *= surfacingSpeedFactor;
|
bubble.speed *= _devSettings.BubbleSurfacingSpeedFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[BubbleSpawner] Started surfacing mode. Bubbles slowed to {surfacingSpeedFactor * 100}% speed.");
|
Debug.Log($"[BubbleSpawner] Started surfacing mode. Bubbles slowed to {_devSettings.BubbleSurfacingSpeedFactor * 100}% speed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.Playables;
|
using UnityEngine.Playables;
|
||||||
|
using AppleHills.Core.Settings;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -13,40 +14,17 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("Array of monster prefabs to spawn randomly")]
|
[Tooltip("Array of monster prefabs to spawn randomly")]
|
||||||
[SerializeField] private GameObject[] monsterPrefabs;
|
[SerializeField] private GameObject[] monsterPrefabs;
|
||||||
|
|
||||||
[Header("Spawn Probability")]
|
|
||||||
[Tooltip("Base chance (0-1) of spawning a monster on each tile")]
|
|
||||||
[SerializeField] private float baseSpawnProbability = 0.2f;
|
|
||||||
[Tooltip("Maximum chance (0-1) of spawning a monster")]
|
|
||||||
[SerializeField] private float maxSpawnProbability = 0.5f;
|
|
||||||
[Tooltip("How fast the probability increases per second")]
|
|
||||||
[SerializeField] private float probabilityIncreaseRate = 0.01f;
|
|
||||||
|
|
||||||
[Header("Spawn Timing")]
|
|
||||||
[Tooltip("Force a spawn after this many seconds without spawns")]
|
|
||||||
[SerializeField] private float guaranteedSpawnTime = 30f;
|
|
||||||
[Tooltip("Minimum time between monster spawns")]
|
|
||||||
[SerializeField] private float spawnCooldown = 5f;
|
|
||||||
|
|
||||||
[Header("Scoring")]
|
|
||||||
[Tooltip("Base points for taking a picture")]
|
|
||||||
[SerializeField] private int basePoints = 100;
|
|
||||||
[Tooltip("Additional points per depth unit")]
|
|
||||||
[SerializeField] private int depthMultiplier = 10;
|
|
||||||
|
|
||||||
[Header("Rope Damage System")]
|
[Header("Rope Damage System")]
|
||||||
[Tooltip("Ropes that will break one by one as player takes damage")]
|
[Tooltip("Ropes that will break one by one as player takes damage")]
|
||||||
[SerializeField] private RopeBreaker[] playerRopes;
|
[SerializeField] private RopeBreaker[] playerRopes;
|
||||||
|
|
||||||
[Header("Surfacing Settings")]
|
[Header("Surfacing Settings")]
|
||||||
[Tooltip("Duration in seconds for speed transition when surfacing")]
|
|
||||||
[SerializeField] private float speedTransitionDuration = 2.0f;
|
|
||||||
[Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
|
|
||||||
[SerializeField] private float surfacingSpeedFactor = 3.0f;
|
|
||||||
[Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
|
|
||||||
[SerializeField] private float surfacingSpawnDelay = 5.0f;
|
|
||||||
[Tooltip("Reference to the PlayableDirector that will play the surfacing timeline")]
|
[Tooltip("Reference to the PlayableDirector that will play the surfacing timeline")]
|
||||||
[SerializeField] private PlayableDirector surfacingTimeline;
|
[SerializeField] private PlayableDirector surfacingTimeline;
|
||||||
|
|
||||||
|
// Settings reference
|
||||||
|
private IDivingMinigameSettings _settings;
|
||||||
|
|
||||||
// Private state variables
|
// Private state variables
|
||||||
private int playerScore = 0;
|
private int playerScore = 0;
|
||||||
private float currentSpawnProbability;
|
private float currentSpawnProbability;
|
||||||
@@ -83,7 +61,15 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
currentSpawnProbability = baseSpawnProbability;
|
// Get settings from GameManager
|
||||||
|
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||||
|
if (_settings == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[DivingGameManager] Failed to load diving minigame settings!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize with base probability from settings
|
||||||
|
currentSpawnProbability = _settings?.EndlessDescenderBaseSpawnProbability ?? 0.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
@@ -118,10 +104,10 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
// Gradually increase spawn probability over time
|
// Gradually increase spawn probability over time
|
||||||
float previousProbability = currentSpawnProbability;
|
float previousProbability = currentSpawnProbability;
|
||||||
if (currentSpawnProbability < maxSpawnProbability)
|
if (currentSpawnProbability < _settings.EndlessDescenderMaxSpawnProbability)
|
||||||
{
|
{
|
||||||
currentSpawnProbability += probabilityIncreaseRate * Time.deltaTime;
|
currentSpawnProbability += _settings.EndlessDescenderProbabilityIncreaseRate * Time.deltaTime;
|
||||||
currentSpawnProbability = Mathf.Min(currentSpawnProbability, maxSpawnProbability);
|
currentSpawnProbability = Mathf.Min(currentSpawnProbability, _settings.EndlessDescenderMaxSpawnProbability);
|
||||||
|
|
||||||
// Only fire event if probability changed significantly
|
// Only fire event if probability changed significantly
|
||||||
if (Mathf.Abs(currentSpawnProbability - previousProbability) > 0.01f)
|
if (Mathf.Abs(currentSpawnProbability - previousProbability) > 0.01f)
|
||||||
@@ -141,8 +127,8 @@ namespace Minigames.DivingForPictures
|
|||||||
// If we're surfacing, don't spawn new monsters
|
// If we're surfacing, don't spawn new monsters
|
||||||
if (_isSurfacing) return;
|
if (_isSurfacing) return;
|
||||||
|
|
||||||
bool forceSpawn = timeSinceLastSpawn >= guaranteedSpawnTime;
|
bool forceSpawn = timeSinceLastSpawn >= _settings.EndlessDescenderGuaranteedSpawnTime;
|
||||||
bool onCooldown = timeSinceLastSpawn < spawnCooldown;
|
bool onCooldown = timeSinceLastSpawn < _settings.EndlessDescenderSpawnCooldown;
|
||||||
|
|
||||||
// Don't spawn if on cooldown, unless forced
|
// Don't spawn if on cooldown, unless forced
|
||||||
if (onCooldown && !forceSpawn) return;
|
if (onCooldown && !forceSpawn) return;
|
||||||
@@ -159,7 +145,7 @@ namespace Minigames.DivingForPictures
|
|||||||
// Reset timer and adjust probability
|
// Reset timer and adjust probability
|
||||||
lastSpawnTime = Time.time;
|
lastSpawnTime = Time.time;
|
||||||
timeSinceLastSpawn = 0f;
|
timeSinceLastSpawn = 0f;
|
||||||
currentSpawnProbability = baseSpawnProbability;
|
currentSpawnProbability = _settings.EndlessDescenderBaseSpawnProbability;
|
||||||
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,8 +190,8 @@ namespace Minigames.DivingForPictures
|
|||||||
private void OnMonsterPictureTaken(Monster monster)
|
private void OnMonsterPictureTaken(Monster monster)
|
||||||
{
|
{
|
||||||
// Calculate points based on depth
|
// Calculate points based on depth
|
||||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * depthMultiplier);
|
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.EndlessDescenderDepthMultiplier);
|
||||||
int pointsAwarded = basePoints + depthBonus;
|
int pointsAwarded = _settings.EndlessDescenderBasePoints + depthBonus;
|
||||||
|
|
||||||
// Add score
|
// Add score
|
||||||
playerScore += pointsAwarded;
|
playerScore += pointsAwarded;
|
||||||
@@ -356,7 +342,7 @@ namespace Minigames.DivingForPictures
|
|||||||
_isSurfacing = true;
|
_isSurfacing = true;
|
||||||
|
|
||||||
// 1. Initiate smooth velocity transition to surfacing speed
|
// 1. Initiate smooth velocity transition to surfacing speed
|
||||||
float targetVelocityFactor = -1.0f * surfacingSpeedFactor;
|
float targetVelocityFactor = -1.0f * _settings.EndlessDescenderSurfacingSpeedFactor;
|
||||||
SetVelocityFactor(targetVelocityFactor);
|
SetVelocityFactor(targetVelocityFactor);
|
||||||
|
|
||||||
// 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
|
// 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
|
||||||
@@ -525,7 +511,7 @@ namespace Minigames.DivingForPictures
|
|||||||
private IEnumerator SurfacingSequence()
|
private IEnumerator SurfacingSequence()
|
||||||
{
|
{
|
||||||
// Wait for the configured delay
|
// Wait for the configured delay
|
||||||
yield return new WaitForSeconds(surfacingSpawnDelay);
|
yield return new WaitForSeconds(_settings.EndlessDescenderSurfacingSpawnDelay);
|
||||||
|
|
||||||
// Find tile spawner and tell it to stop spawning
|
// Find tile spawner and tell it to stop spawning
|
||||||
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||||
@@ -594,10 +580,10 @@ namespace Minigames.DivingForPictures
|
|||||||
float startFactor = _currentVelocityFactor;
|
float startFactor = _currentVelocityFactor;
|
||||||
float elapsed = 0f;
|
float elapsed = 0f;
|
||||||
|
|
||||||
while (elapsed < speedTransitionDuration)
|
while (elapsed < _settings.EndlessDescenderSpeedTransitionDuration)
|
||||||
{
|
{
|
||||||
elapsed += Time.deltaTime;
|
elapsed += Time.deltaTime;
|
||||||
float t = Mathf.Clamp01(elapsed / speedTransitionDuration);
|
float t = Mathf.Clamp01(elapsed / _settings.EndlessDescenderSpeedTransitionDuration);
|
||||||
|
|
||||||
// Smooth step interpolation
|
// Smooth step interpolation
|
||||||
float smoothStep = t * t * (3f - 2f * t);
|
float smoothStep = t * t * (3f - 2f * t);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using Pooling;
|
using Pooling;
|
||||||
|
using AppleHills.Core.Settings;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -16,50 +17,17 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("List of possible obstacle prefabs to spawn")]
|
[Tooltip("List of possible obstacle prefabs to spawn")]
|
||||||
[SerializeField] private List<GameObject> obstaclePrefabs;
|
[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")]
|
[Header("Events")]
|
||||||
[Tooltip("Called when an obstacle is spawned")]
|
[Tooltip("Invoked when a new obstacle is spawned")]
|
||||||
public UnityEvent<GameObject> onObstacleSpawned;
|
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;
|
public UnityEvent<GameObject> onObstacleDestroyed;
|
||||||
|
|
||||||
|
// Settings references
|
||||||
|
private IDivingMinigameSettings _settings;
|
||||||
|
private DivingDeveloperSettings _devSettings;
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
private ObstaclePool _obstaclePool;
|
private ObstaclePool _obstaclePool;
|
||||||
private Camera _mainCamera;
|
private Camera _mainCamera;
|
||||||
@@ -75,13 +43,34 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
_mainCamera = Camera.main;
|
_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
|
// Validate obstacle prefabs
|
||||||
ValidateObstaclePrefabs();
|
ValidateObstaclePrefabs();
|
||||||
|
|
||||||
if (useObjectPooling)
|
if (_devSettings?.ObstacleUseObjectPooling ?? false)
|
||||||
{
|
{
|
||||||
InitializeObjectPool();
|
InitializeObjectPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize events if null
|
||||||
|
if (onObstacleSpawned == null)
|
||||||
|
onObstacleSpawned = new UnityEvent<GameObject>();
|
||||||
|
|
||||||
|
if (onObstacleDestroyed == null)
|
||||||
|
onObstacleDestroyed = new UnityEvent<GameObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
@@ -100,6 +89,8 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void ValidateObstaclePrefabs()
|
private void ValidateObstaclePrefabs()
|
||||||
{
|
{
|
||||||
|
if (_devSettings == null) return;
|
||||||
|
|
||||||
for (int i = 0; i < obstaclePrefabs.Count; i++)
|
for (int i = 0; i < obstaclePrefabs.Count; i++)
|
||||||
{
|
{
|
||||||
if (obstaclePrefabs[i] == null) continue;
|
if (obstaclePrefabs[i] == null) continue;
|
||||||
@@ -112,10 +103,10 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the prefab is on the correct layer (using configurable obstacleLayer)
|
// 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.");
|
Debug.LogWarning($"Obstacle prefab {obstaclePrefabs[i].name} is not on the configured obstacle layer ({_devSettings.ObstacleLayer}). Setting layer automatically.");
|
||||||
SetLayerRecursively(obstaclePrefabs[i], obstacleLayer);
|
SetLayerRecursively(obstaclePrefabs[i], _devSettings.ObstacleLayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,8 +133,8 @@ namespace Minigames.DivingForPictures
|
|||||||
_obstaclePool = poolGO.AddComponent<ObstaclePool>();
|
_obstaclePool = poolGO.AddComponent<ObstaclePool>();
|
||||||
|
|
||||||
// Set up pool configuration
|
// Set up pool configuration
|
||||||
_obstaclePool.maxPerPrefabPoolSize = maxPerPrefabPoolSize;
|
_obstaclePool.maxPerPrefabPoolSize = _devSettings.ObstacleMaxPerPrefabPoolSize;
|
||||||
_obstaclePool.totalMaxPoolSize = totalMaxPoolSize;
|
_obstaclePool.totalMaxPoolSize = _devSettings.ObstacleTotalMaxPoolSize;
|
||||||
|
|
||||||
// Convert GameObject list to FloatingObstacle list
|
// Convert GameObject list to FloatingObstacle list
|
||||||
List<FloatingObstacle> prefabObstacles = new List<FloatingObstacle>(obstaclePrefabs.Count);
|
List<FloatingObstacle> prefabObstacles = new List<FloatingObstacle>(obstaclePrefabs.Count);
|
||||||
@@ -230,7 +221,9 @@ namespace Minigames.DivingForPictures
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Calculate next spawn time with variation
|
// 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
|
nextSpawnTime = Mathf.Max(0.1f, nextSpawnTime); // Ensure minimum interval
|
||||||
|
|
||||||
yield return new WaitForSeconds(nextSpawnTime);
|
yield return new WaitForSeconds(nextSpawnTime);
|
||||||
@@ -264,7 +257,7 @@ namespace Minigames.DivingForPictures
|
|||||||
bool foundValidPosition = false;
|
bool foundValidPosition = false;
|
||||||
|
|
||||||
// Try to find a valid spawn position
|
// Try to find a valid spawn position
|
||||||
for (int attempts = 0; attempts < maxSpawnAttempts; attempts++)
|
for (int attempts = 0; attempts < _settings.EndlessDescenderObstacleMaxSpawnAttempts; attempts++)
|
||||||
{
|
{
|
||||||
spawnPosition = GetRandomSpawnPosition();
|
spawnPosition = GetRandomSpawnPosition();
|
||||||
|
|
||||||
@@ -277,13 +270,13 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{maxSpawnAttempts})");
|
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{_settings.EndlessDescenderObstacleMaxSpawnAttempts})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundValidPosition)
|
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)
|
private bool IsValidSpawnPosition(Vector3 position)
|
||||||
{
|
{
|
||||||
// Use OverlapCircle to check for collisions with tiles
|
// 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;
|
return collision == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +323,7 @@ namespace Minigames.DivingForPictures
|
|||||||
GameObject obstacle;
|
GameObject obstacle;
|
||||||
|
|
||||||
// Spawn using pool or instantiate directly
|
// 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})");
|
Debug.Log($"[ObstacleSpawner] Requesting obstacle from pool (prefab index {prefabIndex})");
|
||||||
obstacle = _obstaclePool.GetObstacle(prefabIndex);
|
obstacle = _obstaclePool.GetObstacle(prefabIndex);
|
||||||
@@ -416,8 +409,10 @@ namespace Minigames.DivingForPictures
|
|||||||
// Set prefab index
|
// Set prefab index
|
||||||
obstacleComponent.PrefabIndex = prefabIndex;
|
obstacleComponent.PrefabIndex = prefabIndex;
|
||||||
|
|
||||||
// Randomize properties
|
// Randomize properties using settings
|
||||||
obstacleComponent.MoveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed);
|
obstacleComponent.MoveSpeed = Random.Range(
|
||||||
|
_settings.EndlessDescenderObstacleMinMoveSpeed,
|
||||||
|
_settings.EndlessDescenderObstacleMaxMoveSpeed);
|
||||||
|
|
||||||
// Set spawner reference (since FloatingObstacle has this built-in now)
|
// Set spawner reference (since FloatingObstacle has this built-in now)
|
||||||
obstacleComponent.SetSpawner(this);
|
obstacleComponent.SetSpawner(this);
|
||||||
@@ -440,7 +435,7 @@ namespace Minigames.DivingForPictures
|
|||||||
onObstacleDestroyed?.Invoke(obstacle);
|
onObstacleDestroyed?.Invoke(obstacle);
|
||||||
|
|
||||||
// Return to pool or destroy
|
// Return to pool or destroy
|
||||||
if (useObjectPooling && _obstaclePool != null)
|
if (_devSettings.ObstacleUseObjectPooling && _obstaclePool != null)
|
||||||
{
|
{
|
||||||
Debug.Log($"[ObstacleSpawner] Returning {obstacle.name} to pool");
|
Debug.Log($"[ObstacleSpawner] Returning {obstacle.name} to pool");
|
||||||
_obstaclePool.ReturnObstacle(obstacle, prefabIndex);
|
_obstaclePool.ReturnObstacle(obstacle, prefabIndex);
|
||||||
@@ -457,7 +452,9 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetSpawnInterval(float interval)
|
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>
|
/// <summary>
|
||||||
@@ -465,8 +462,9 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetSpeedRange(float min, float max)
|
public void SetSpeedRange(float min, float max)
|
||||||
{
|
{
|
||||||
minMoveSpeed = min;
|
// This method can no longer directly modify the settings
|
||||||
maxMoveSpeed = max;
|
// Consider implementing a runtime settings override system if needed
|
||||||
|
Debug.LogWarning("[ObstacleSpawner] SetSpeedRange no longer modifies settings directly. Settings are now centralized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -534,8 +532,8 @@ namespace Minigames.DivingForPictures
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private void OnDrawGizmosSelected()
|
private void OnDrawGizmosSelected()
|
||||||
{
|
{
|
||||||
// Only draw if screen bounds have been calculated
|
// Only draw if screen bounds have been calculated and settings are available
|
||||||
if (_spawnRangeX > 0f)
|
if (_spawnRangeX > 0f && _settings != null)
|
||||||
{
|
{
|
||||||
// Draw spawn area using dynamic calculations
|
// Draw spawn area using dynamic calculations
|
||||||
Gizmos.color = Color.yellow;
|
Gizmos.color = Color.yellow;
|
||||||
@@ -545,7 +543,7 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
// Draw collision radius at spawn point
|
// Draw collision radius at spawn point
|
||||||
Gizmos.color = Color.red;
|
Gizmos.color = Color.red;
|
||||||
Gizmos.DrawWireSphere(center, spawnCollisionRadius);
|
Gizmos.DrawWireSphere(center, _settings.EndlessDescenderObstacleSpawnCollisionRadius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using AppleHills.Core.Settings;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -8,11 +9,8 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PlayerController : MonoBehaviour, ITouchInputConsumer
|
public class PlayerController : MonoBehaviour, ITouchInputConsumer
|
||||||
{
|
{
|
||||||
[Header("Tap Movement")]
|
// Settings reference
|
||||||
[Tooltip("Maximum distance the player can move from a single tap")]
|
private IDivingMinigameSettings _settings;
|
||||||
[SerializeField] private float tapMaxDistance = 0.5f;
|
|
||||||
[Tooltip("How quickly the tap impulse fades (higher = faster stop)")]
|
|
||||||
[SerializeField] private float tapDecelerationRate = 5.0f;
|
|
||||||
|
|
||||||
private float _targetFingerX;
|
private float _targetFingerX;
|
||||||
private bool _isTouchActive;
|
private bool _isTouchActive;
|
||||||
@@ -25,6 +23,13 @@ namespace Minigames.DivingForPictures
|
|||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
_originY = transform.position.y;
|
_originY = transform.position.y;
|
||||||
|
|
||||||
|
// Get settings from GameManager
|
||||||
|
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||||
|
if (_settings == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[PlayerController] Failed to load diving minigame settings!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
@@ -42,7 +47,7 @@ namespace Minigames.DivingForPictures
|
|||||||
public void OnTap(Vector2 worldPosition)
|
public void OnTap(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
// Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
|
// Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
|
||||||
float targetX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
float targetX = Mathf.Clamp(worldPosition.x, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax);
|
||||||
|
|
||||||
// Calculate tap direction (+1 for right, -1 for left)
|
// Calculate tap direction (+1 for right, -1 for left)
|
||||||
_tapDirection = Mathf.Sign(targetX - transform.position.x);
|
_tapDirection = Mathf.Sign(targetX - transform.position.x);
|
||||||
@@ -63,7 +68,7 @@ namespace Minigames.DivingForPictures
|
|||||||
public void OnHoldStart(Vector2 worldPosition)
|
public void OnHoldStart(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
// Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
|
// Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
|
||||||
_targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
_targetFingerX = Mathf.Clamp(worldPosition.x, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax);
|
||||||
_isTouchActive = true;
|
_isTouchActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +78,7 @@ namespace Minigames.DivingForPictures
|
|||||||
public void OnHoldMove(Vector2 worldPosition)
|
public void OnHoldMove(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
// Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
|
// Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
|
||||||
_targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
_targetFingerX = Mathf.Clamp(worldPosition.x, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -91,9 +96,9 @@ namespace Minigames.DivingForPictures
|
|||||||
if (_isTouchActive)
|
if (_isTouchActive)
|
||||||
{
|
{
|
||||||
float currentX = transform.position.x;
|
float currentX = transform.position.x;
|
||||||
float lerpSpeed = GameManager.Instance.EndlessDescenderLerpSpeed;
|
float lerpSpeed = _settings.EndlessDescenderLerpSpeed;
|
||||||
float maxOffset = GameManager.Instance.EndlessDescenderMaxOffset;
|
float maxOffset = _settings.EndlessDescenderMaxOffset;
|
||||||
float exponent = GameManager.Instance.EndlessDescenderSpeedExponent;
|
float exponent = _settings.EndlessDescenderSpeedExponent;
|
||||||
float targetX = _targetFingerX;
|
float targetX = _targetFingerX;
|
||||||
float offset = targetX - currentX;
|
float offset = targetX - currentX;
|
||||||
offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
|
offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
|
||||||
@@ -103,7 +108,7 @@ namespace Minigames.DivingForPictures
|
|||||||
// Prevent overshooting
|
// Prevent overshooting
|
||||||
moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
|
moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
|
||||||
float newX = currentX + moveStep;
|
float newX = currentX + moveStep;
|
||||||
newX = Mathf.Clamp(newX, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
newX = Mathf.Clamp(newX, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax);
|
||||||
|
|
||||||
UpdatePosition(newX);
|
UpdatePosition(newX);
|
||||||
}
|
}
|
||||||
@@ -111,21 +116,21 @@ namespace Minigames.DivingForPictures
|
|||||||
else if (_tapImpulseStrength > 0)
|
else if (_tapImpulseStrength > 0)
|
||||||
{
|
{
|
||||||
float currentX = transform.position.x;
|
float currentX = transform.position.x;
|
||||||
float maxOffset = GameManager.Instance.EndlessDescenderMaxOffset;
|
float maxOffset = _settings.EndlessDescenderMaxOffset;
|
||||||
float lerpSpeed = GameManager.Instance.EndlessDescenderLerpSpeed;
|
float lerpSpeed = _settings.EndlessDescenderLerpSpeed;
|
||||||
|
|
||||||
// Calculate move distance based on impulse strength
|
// Calculate move distance based on impulse strength
|
||||||
float moveDistance = maxOffset * _tapImpulseStrength * Time.deltaTime * lerpSpeed;
|
float moveDistance = maxOffset * _tapImpulseStrength * Time.deltaTime * lerpSpeed;
|
||||||
|
|
||||||
// Limit total movement from single tap
|
// Limit total movement from single tap
|
||||||
moveDistance = Mathf.Min(moveDistance, tapMaxDistance * _tapImpulseStrength);
|
moveDistance = Mathf.Min(moveDistance, _settings.EndlessDescenderTapMaxDistance * _tapImpulseStrength);
|
||||||
|
|
||||||
// Apply movement in tap direction
|
// Apply movement in tap direction
|
||||||
float newX = currentX + (moveDistance * _tapDirection);
|
float newX = currentX + (moveDistance * _tapDirection);
|
||||||
newX = Mathf.Clamp(newX, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
newX = Mathf.Clamp(newX, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax);
|
||||||
|
|
||||||
// Reduce impulse strength over time
|
// Reduce impulse strength over time
|
||||||
_tapImpulseStrength -= Time.deltaTime * tapDecelerationRate;
|
_tapImpulseStrength -= Time.deltaTime * _settings.EndlessDescenderTapDecelerationRate;
|
||||||
if (_tapImpulseStrength < 0.01f)
|
if (_tapImpulseStrength < 0.01f)
|
||||||
{
|
{
|
||||||
_tapImpulseStrength = 0f;
|
_tapImpulseStrength = 0f;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
using Pooling;
|
using Pooling;
|
||||||
|
using AppleHills.Core.Settings;
|
||||||
|
|
||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
@@ -16,16 +17,6 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("List of possible trench tile prefabs.")]
|
[Tooltip("List of possible trench tile prefabs.")]
|
||||||
[SerializeField] private List<GameObject> tilePrefabs;
|
[SerializeField] private List<GameObject> tilePrefabs;
|
||||||
|
|
||||||
[Header("Tile Settings")]
|
|
||||||
[SerializeField] private int initialTileCount = 3;
|
|
||||||
[SerializeField] private float tileSpawnBuffer = 1f;
|
|
||||||
|
|
||||||
[Header("Movement Settings")]
|
|
||||||
[SerializeField] private float moveSpeed = 3f;
|
|
||||||
[SerializeField] private float speedUpFactor = 0.2f;
|
|
||||||
[SerializeField] private float speedUpInterval = 10f;
|
|
||||||
[SerializeField] private float maxMoveSpeed = 12f;
|
|
||||||
|
|
||||||
[Header("Object Pooling")]
|
[Header("Object Pooling")]
|
||||||
[SerializeField] private bool useObjectPooling = true;
|
[SerializeField] private bool useObjectPooling = true;
|
||||||
[SerializeField] private int maxPerPrefabPoolSize = 2;
|
[SerializeField] private int maxPerPrefabPoolSize = 2;
|
||||||
@@ -38,6 +29,9 @@ namespace Minigames.DivingForPictures
|
|||||||
[FormerlySerializedAs("OnTileDestroyed")]
|
[FormerlySerializedAs("OnTileDestroyed")]
|
||||||
public UnityEvent<GameObject> onTileDestroyed;
|
public UnityEvent<GameObject> onTileDestroyed;
|
||||||
|
|
||||||
|
// Settings reference
|
||||||
|
private IDivingMinigameSettings _settings;
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
private readonly Dictionary<GameObject, float> _tileHeights = new Dictionary<GameObject, float>();
|
private readonly Dictionary<GameObject, float> _tileHeights = new Dictionary<GameObject, float>();
|
||||||
private readonly List<GameObject> _activeTiles = new List<GameObject>();
|
private readonly List<GameObject> _activeTiles = new List<GameObject>();
|
||||||
@@ -53,9 +47,6 @@ namespace Minigames.DivingForPictures
|
|||||||
// Current velocity for tile movement
|
// Current velocity for tile movement
|
||||||
private float _currentVelocity;
|
private float _currentVelocity;
|
||||||
|
|
||||||
// Interval for velocity calculations (seconds)
|
|
||||||
[SerializeField] private float velocityCalculationInterval = 0.5f;
|
|
||||||
|
|
||||||
private const float TileSpawnZ = -1f;
|
private const float TileSpawnZ = -1f;
|
||||||
private const float DefaultTileHeight = 5f;
|
private const float DefaultTileHeight = 5f;
|
||||||
|
|
||||||
@@ -73,7 +64,15 @@ namespace Minigames.DivingForPictures
|
|||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_mainCamera = Camera.main;
|
_mainCamera = Camera.main;
|
||||||
_baseMoveSpeed = moveSpeed; // Store the original base speed
|
|
||||||
|
// Get settings from GameManager
|
||||||
|
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||||
|
if (_settings == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[TrenchTileSpawner] Failed to load diving minigame settings!");
|
||||||
|
}
|
||||||
|
|
||||||
|
_baseMoveSpeed = _settings?.EndlessDescenderMoveSpeed ?? 3f; // Store the original base speed
|
||||||
|
|
||||||
// Calculate tile heights for each prefab
|
// Calculate tile heights for each prefab
|
||||||
CalculateTileHeights();
|
CalculateTileHeights();
|
||||||
@@ -110,7 +109,7 @@ namespace Minigames.DivingForPictures
|
|||||||
SpawnInitialTiles();
|
SpawnInitialTiles();
|
||||||
|
|
||||||
// Initialize velocity and start the velocity calculation coroutine
|
// Initialize velocity and start the velocity calculation coroutine
|
||||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
_currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime;
|
||||||
StartCoroutine(VelocityCalculationRoutine());
|
StartCoroutine(VelocityCalculationRoutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +147,7 @@ namespace Minigames.DivingForPictures
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
CalculateVelocity();
|
CalculateVelocity();
|
||||||
yield return new WaitForSeconds(velocityCalculationInterval);
|
yield return new WaitForSeconds(_settings.EndlessDescenderVelocityCalculationInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +156,7 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void CalculateVelocity()
|
private void CalculateVelocity()
|
||||||
{
|
{
|
||||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
_currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -247,7 +246,7 @@ namespace Minigames.DivingForPictures
|
|||||||
// Move starting position up by 2 tile heights
|
// Move starting position up by 2 tile heights
|
||||||
startingY += tileHeightEstimate * 2;
|
startingY += tileHeightEstimate * 2;
|
||||||
|
|
||||||
for (int i = 0; i < initialTileCount; i++)
|
for (int i = 0; i < _settings.EndlessDescenderInitialTileCount; i++)
|
||||||
{
|
{
|
||||||
float y = startingY;
|
float y = startingY;
|
||||||
// Calculate proper Y position based on previous tiles
|
// Calculate proper Y position based on previous tiles
|
||||||
@@ -291,12 +290,12 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
// Update the actual move speed based on the velocity factor
|
// Update the actual move speed based on the velocity factor
|
||||||
// This keeps the original move speed intact for game logic
|
// This keeps the original move speed intact for game logic
|
||||||
moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
|
_baseMoveSpeed = _settings.EndlessDescenderMoveSpeed * Mathf.Abs(_velocityFactor);
|
||||||
|
|
||||||
// Recalculate velocity immediately
|
// Recalculate velocity immediately
|
||||||
CalculateVelocity();
|
CalculateVelocity();
|
||||||
|
|
||||||
Debug.Log($"[TrenchTileSpawner] Velocity factor updated to {_velocityFactor:F2}, moveSpeed: {moveSpeed:F2}");
|
Debug.Log($"[TrenchTileSpawner] Velocity factor updated to {_velocityFactor:F2}, moveSpeed: {_baseMoveSpeed:F2}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -362,12 +361,12 @@ namespace Minigames.DivingForPictures
|
|||||||
if (_isSurfacing)
|
if (_isSurfacing)
|
||||||
{
|
{
|
||||||
// When surfacing, destroy tiles at the bottom
|
// When surfacing, destroy tiles at the bottom
|
||||||
shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When descending, destroy tiles at the top
|
// When descending, destroy tiles at the top
|
||||||
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldDestroy)
|
if (shouldDestroy)
|
||||||
@@ -431,12 +430,12 @@ namespace Minigames.DivingForPictures
|
|||||||
if (_isSurfacing)
|
if (_isSurfacing)
|
||||||
{
|
{
|
||||||
// When surfacing, check if the bottom of the tile is above the top of the screen
|
// When surfacing, check if the bottom of the tile is above the top of the screen
|
||||||
isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When descending, check if the top of the tile is below the bottom of the screen
|
// When descending, check if the top of the tile is below the bottom of the screen
|
||||||
isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLastTileLeaving)
|
if (isLastTileLeaving)
|
||||||
@@ -454,14 +453,14 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
// When surfacing, spawn new tiles at the top
|
// When surfacing, spawn new tiles at the top
|
||||||
float topEdge = bottomTile.transform.position.y + tileHeight / 2;
|
float topEdge = bottomTile.transform.position.y + tileHeight / 2;
|
||||||
shouldSpawn = topEdge < _screenTop + tileSpawnBuffer;
|
shouldSpawn = topEdge < _screenTop + _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
newY = bottomTile.transform.position.y + tileHeight;
|
newY = bottomTile.transform.position.y + tileHeight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When descending, spawn new tiles at the bottom
|
// When descending, spawn new tiles at the bottom
|
||||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||||
shouldSpawn = bottomEdge > _screenBottom - tileSpawnBuffer;
|
shouldSpawn = bottomEdge > _screenBottom - _settings.EndlessDescenderTileSpawnBuffer;
|
||||||
newY = bottomTile.transform.position.y - tileHeight;
|
newY = bottomTile.transform.position.y - tileHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,9 +476,9 @@ namespace Minigames.DivingForPictures
|
|||||||
private void HandleSpeedRamping()
|
private void HandleSpeedRamping()
|
||||||
{
|
{
|
||||||
_speedUpTimer += Time.deltaTime;
|
_speedUpTimer += Time.deltaTime;
|
||||||
if (_speedUpTimer >= speedUpInterval)
|
if (_speedUpTimer >= _settings.EndlessDescenderSpeedUpInterval)
|
||||||
{
|
{
|
||||||
moveSpeed = Mathf.Min(moveSpeed + speedUpFactor, maxMoveSpeed);
|
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.EndlessDescenderSpeedUpFactor, _settings.EndlessDescenderMaxMoveSpeed);
|
||||||
_speedUpTimer = 0f;
|
_speedUpTimer = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -656,7 +655,9 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
// Draw tile bounds for debugging
|
// Draw tile bounds for debugging
|
||||||
Gizmos.color = Color.cyan;
|
Gizmos.color = Color.cyan;
|
||||||
for (int i = 0; i < initialTileCount; i++)
|
if (_settings != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _settings.EndlessDescenderInitialTileCount; i++)
|
||||||
{
|
{
|
||||||
float height = DefaultTileHeight;
|
float height = DefaultTileHeight;
|
||||||
if (tilePrefabs != null && tilePrefabs.Count > 0 && tilePrefabs[0] != null &&
|
if (tilePrefabs != null && tilePrefabs.Count > 0 && tilePrefabs[0] != null &&
|
||||||
@@ -668,6 +669,7 @@ namespace Minigames.DivingForPictures
|
|||||||
Gizmos.DrawWireCube(center, new Vector3(10f, height, 1f));
|
Gizmos.DrawWireCube(center, new Vector3(10f, height, 1f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user