From 348e982930d7f2f4fca49cce5857046700aeb4de Mon Sep 17 00:00:00 2001 From: Michal Pikulski Date: Tue, 7 Oct 2025 09:28:41 +0200 Subject: [PATCH] Use normalized movement settings --- Assets/Resources/PerformanceTestRunInfo.json | 1 - .../Resources/PerformanceTestRunSettings.json | 1 - .../Core/Settings/DivingMinigameSettings.cs | 43 ++- .../Core/Settings/SettingsInterfaces.cs | 13 +- .../Obstacles/FloatingObstacle.cs | 57 +++- .../Tiles/TrenchTileSpawner.cs | 322 +++++++++++++++++- Assets/Settings/DivingMinigameSettings.asset | 9 +- 7 files changed, 398 insertions(+), 48 deletions(-) delete mode 100644 Assets/Resources/PerformanceTestRunInfo.json delete mode 100644 Assets/Resources/PerformanceTestRunSettings.json diff --git a/Assets/Resources/PerformanceTestRunInfo.json b/Assets/Resources/PerformanceTestRunInfo.json deleted file mode 100644 index e1756812..00000000 --- a/Assets/Resources/PerformanceTestRunInfo.json +++ /dev/null @@ -1 +0,0 @@ -{"TestSuite":"","Date":0,"Player":{"Development":false,"ScreenWidth":0,"ScreenHeight":0,"ScreenRefreshRate":0,"Fullscreen":false,"Vsync":0,"AntiAliasing":0,"Batchmode":false,"RenderThreadingMode":"MultiThreaded","GpuSkinning":false,"Platform":"","ColorSpace":"","AnisotropicFiltering":"","BlendWeights":"","GraphicsApi":"","ScriptingBackend":"IL2CPP","AndroidTargetSdkVersion":"AndroidApiLevelAuto","AndroidBuildSystem":"Gradle","BuildTarget":"Android","StereoRenderingPath":"MultiPass"},"Hardware":{"OperatingSystem":"","DeviceModel":"","DeviceName":"","ProcessorType":"","ProcessorCount":0,"GraphicsDeviceName":"","SystemMemorySizeMB":0},"Editor":{"Version":"6000.2.6f1","Branch":"6000.2/staging","Changeset":"cc51a95c0300","Date":1758053328},"Dependencies":["com.unity.2d.sprite@1.0.0","com.unity.2d.spriteshape@12.0.1","com.unity.addressables@2.7.3","com.unity.addressables.android@1.0.7","com.unity.cinemachine@3.1.4","com.unity.feature.2d@2.0.1","com.unity.film-internal-utilities@0.18.4-preview","com.unity.graphtoolkit@0.4.0-exp.2","com.unity.ide.rider@3.0.38","com.unity.ide.visualstudio@2.0.23","com.unity.inputsystem@1.14.2","com.unity.multiplayer.center@1.0.0","com.unity.render-pipelines.universal@17.2.0","com.unity.timeline@1.8.9","com.unity.ugui@2.0.0","com.unity.modules.accessibility@1.0.0","com.unity.modules.ai@1.0.0","com.unity.modules.androidjni@1.0.0","com.unity.modules.animation@1.0.0","com.unity.modules.assetbundle@1.0.0","com.unity.modules.audio@1.0.0","com.unity.modules.cloth@1.0.0","com.unity.modules.director@1.0.0","com.unity.modules.imageconversion@1.0.0","com.unity.modules.imgui@1.0.0","com.unity.modules.jsonserialize@1.0.0","com.unity.modules.particlesystem@1.0.0","com.unity.modules.physics@1.0.0","com.unity.modules.physics2d@1.0.0","com.unity.modules.screencapture@1.0.0","com.unity.modules.terrain@1.0.0","com.unity.modules.terrainphysics@1.0.0","com.unity.modules.tilemap@1.0.0","com.unity.modules.ui@1.0.0","com.unity.modules.uielements@1.0.0","com.unity.modules.umbra@1.0.0","com.unity.modules.unityanalytics@1.0.0","com.unity.modules.unitywebrequest@1.0.0","com.unity.modules.unitywebrequestassetbundle@1.0.0","com.unity.modules.unitywebrequestaudio@1.0.0","com.unity.modules.unitywebrequesttexture@1.0.0","com.unity.modules.unitywebrequestwww@1.0.0","com.unity.modules.vehicles@1.0.0","com.unity.modules.video@1.0.0","com.unity.modules.vr@1.0.0","com.unity.modules.wind@1.0.0","com.unity.modules.xr@1.0.0","com.unity.modules.subsystems@1.0.0","com.unity.modules.hierarchycore@1.0.0","com.unity.render-pipelines.core@17.2.0","com.unity.shadergraph@17.2.0","com.unity.render-pipelines.universal-config@17.0.3","com.unity.test-framework@1.6.0","com.unity.ext.nunit@2.0.5","com.unity.2d.animation@12.0.2","com.unity.2d.pixel-perfect@5.1.0","com.unity.2d.psdimporter@11.0.1","com.unity.2d.tilemap@1.0.0","com.unity.2d.tilemap.extras@5.0.1","com.unity.2d.aseprite@2.0.1","com.unity.splines@2.8.2","com.unity.profiling.core@1.0.2","com.unity.scriptablebuildpipeline@2.4.2","com.unity.2d.common@11.0.1","com.unity.mathematics@1.3.2","com.unity.searcher@4.9.3","com.unity.burst@1.8.24","com.unity.collections@2.5.7","com.unity.rendering.light-transport@1.0.1","com.unity.settings-manager@2.1.0","com.unity.nuget.mono-cecil@1.11.5","com.unity.test-framework.performance@3.1.0"],"Results":[]} \ No newline at end of file diff --git a/Assets/Resources/PerformanceTestRunSettings.json b/Assets/Resources/PerformanceTestRunSettings.json deleted file mode 100644 index 49438ae1..00000000 --- a/Assets/Resources/PerformanceTestRunSettings.json +++ /dev/null @@ -1 +0,0 @@ -{"MeasurementCount":-1} \ No newline at end of file diff --git a/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs b/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs index f12da829..4a395ac9 100644 --- a/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs +++ b/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs @@ -64,6 +64,10 @@ namespace AppleHills.Core.Settings [Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")] [SerializeField] private float surfacingSpawnDelay = 5.0f; + [Header("Normalized Movement")] + [Tooltip("Reference screen height for normalized velocity calculations")] + [SerializeField] private float referenceScreenHeight = 1080f; + [Header("Tile Generation")] [Tooltip("Initial number of tiles to create at start")] [SerializeField] private int initialTileCount = 3; @@ -71,17 +75,21 @@ namespace AppleHills.Core.Settings [Tooltip("Buffer distance for spawning new tiles")] [SerializeField] private float tileSpawnBuffer = 1f; - [Tooltip("Base movement speed for tiles")] - [SerializeField] private float moveSpeed = 3f; + [Tooltip("Base movement speed for tiles in screen units per second (normalized)")] + [SerializeField] private float normalizedTileMoveSpeed = 0.3f; [Tooltip("Factor to increase speed by each interval")] - [SerializeField] private float speedUpFactor = 0.2f; + [SerializeField] private float speedUpFactor = 0.05f; [Tooltip("Time interval between speed increases (seconds)")] [SerializeField] private float speedUpInterval = 10f; - [Tooltip("Maximum movement speed allowed")] - [SerializeField] private float maxMoveSpeed = 12f; + [Tooltip("Maximum normalized movement speed allowed for tiles")] + [SerializeField] private float maxNormalizedTileMoveSpeed = 1.2f; + + // Legacy settings - keeping for backward compatibility + [HideInInspector] [SerializeField] private float moveSpeed = 3f; + [HideInInspector] [SerializeField] private float maxMoveSpeed = 12f; [Tooltip("Interval for velocity calculations (seconds)")] [SerializeField] private float velocityCalculationInterval = 0.5f; @@ -99,11 +107,11 @@ namespace AppleHills.Core.Settings [Tooltip("Radius around obstacle spawn point to check for tile collisions")] [SerializeField] private float obstacleSpawnCollisionRadius = 1f; - [Tooltip("Minimum movement speed for spawned obstacles")] - [SerializeField] private float obstacleMinMoveSpeed = 1f; + [Tooltip("Minimum normalized movement speed for obstacles (screen units per second)")] + [SerializeField] private float normalizedObstacleMinMoveSpeed = 0.1f; - [Tooltip("Maximum movement speed for spawned obstacles")] - [SerializeField] private float obstacleMaxMoveSpeed = 4f; + [Tooltip("Maximum normalized movement speed for obstacles (screen units per second)")] + [SerializeField] private float normalizedObstacleMaxMoveSpeed = 0.4f; [Header("Collision Handling")] [Tooltip("Duration in seconds of damage immunity after being hit")] @@ -148,10 +156,11 @@ namespace AppleHills.Core.Settings // IDivingMinigameSettings implementation - Tile Generation public int InitialTileCount => initialTileCount; public float TileSpawnBuffer => tileSpawnBuffer; - public float MoveSpeed => moveSpeed; + public float ReferenceScreenHeight => referenceScreenHeight; + public float NormalizedMoveSpeed => normalizedTileMoveSpeed; public float SpeedUpFactor => speedUpFactor; public float SpeedUpInterval => speedUpInterval; - public float MaxMoveSpeed => maxMoveSpeed; + public float MaxNormalizedMoveSpeed => maxNormalizedTileMoveSpeed; public float VelocityCalculationInterval => velocityCalculationInterval; // IDivingMinigameSettings implementation - Obstacles @@ -159,8 +168,8 @@ namespace AppleHills.Core.Settings public float ObstacleSpawnIntervalVariation => obstacleSpawnIntervalVariation; public int ObstacleMaxSpawnAttempts => obstacleMaxSpawnAttempts; public float ObstacleSpawnCollisionRadius => obstacleSpawnCollisionRadius; - public float ObstacleMinMoveSpeed => obstacleMinMoveSpeed; - public float ObstacleMaxMoveSpeed => obstacleMaxMoveSpeed; + public float ObstacleMinMoveSpeed => normalizedObstacleMinMoveSpeed; + public float ObstacleMaxMoveSpeed => normalizedObstacleMaxMoveSpeed; // IDivingMinigameSettings implementation - Collision Handling public float DamageImmunityDuration => damageImmunityDuration; @@ -211,10 +220,10 @@ namespace AppleHills.Core.Settings // Validate tile generation initialTileCount = Mathf.Max(1, initialTileCount); tileSpawnBuffer = Mathf.Max(0f, tileSpawnBuffer); - moveSpeed = Mathf.Max(0.1f, moveSpeed); + normalizedTileMoveSpeed = Mathf.Max(0.01f, normalizedTileMoveSpeed); speedUpFactor = Mathf.Max(0f, speedUpFactor); speedUpInterval = Mathf.Max(0.1f, speedUpInterval); - maxMoveSpeed = Mathf.Max(moveSpeed, maxMoveSpeed); + maxNormalizedTileMoveSpeed = Mathf.Max(normalizedTileMoveSpeed, maxNormalizedTileMoveSpeed); velocityCalculationInterval = Mathf.Max(0.01f, velocityCalculationInterval); // Validate obstacle values @@ -222,8 +231,8 @@ namespace AppleHills.Core.Settings obstacleSpawnIntervalVariation = Mathf.Max(0f, obstacleSpawnIntervalVariation); obstacleMaxSpawnAttempts = Mathf.Max(1, obstacleMaxSpawnAttempts); obstacleSpawnCollisionRadius = Mathf.Max(0.1f, obstacleSpawnCollisionRadius); - obstacleMinMoveSpeed = Mathf.Max(0.1f, obstacleMinMoveSpeed); - obstacleMaxMoveSpeed = Mathf.Max(obstacleMinMoveSpeed, obstacleMaxMoveSpeed); + normalizedObstacleMinMoveSpeed = Mathf.Max(0.1f, normalizedObstacleMinMoveSpeed); + normalizedObstacleMaxMoveSpeed = Mathf.Max(normalizedObstacleMinMoveSpeed, normalizedObstacleMaxMoveSpeed); // Validate collision settings damageImmunityDuration = Mathf.Max(0.1f, damageImmunityDuration); diff --git a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs index eb00e754..5cc343a8 100644 --- a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs +++ b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs @@ -79,19 +79,24 @@ namespace AppleHills.Core.Settings // Tile Generation int InitialTileCount { get; } float TileSpawnBuffer { get; } - float MoveSpeed { get; } float SpeedUpFactor { get; } float SpeedUpInterval { get; } - float MaxMoveSpeed { get; } float VelocityCalculationInterval { get; } + // Normalized Movement + float ReferenceScreenHeight { get; } // Screen height reference for normalized velocities + + // Normalized Tile Movement + float NormalizedMoveSpeed { get; } // Gets normalizedTileMoveSpeed + float MaxNormalizedMoveSpeed { get; } // Gets maxNormalizedTileMoveSpeed + // Obstacles float ObstacleSpawnInterval { get; } float ObstacleSpawnIntervalVariation { get; } int ObstacleMaxSpawnAttempts { get; } float ObstacleSpawnCollisionRadius { get; } - float ObstacleMinMoveSpeed { get; } - float ObstacleMaxMoveSpeed { get; } + float ObstacleMinMoveSpeed { get; } // Gets normalizedObstacleMinMoveSpeed + float ObstacleMaxMoveSpeed { get; } // Gets normalizedObstacleMaxMoveSpeed // Collision Handling float DamageImmunityDuration { get; } diff --git a/Assets/Scripts/Minigames/DivingForPictures/Obstacles/FloatingObstacle.cs b/Assets/Scripts/Minigames/DivingForPictures/Obstacles/FloatingObstacle.cs index 2d285271..03b8ffb7 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Obstacles/FloatingObstacle.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Obstacles/FloatingObstacle.cs @@ -1,5 +1,6 @@ using UnityEngine; using System.Collections; +using AppleHills.Core.Settings; using Pooling; namespace Minigames.DivingForPictures @@ -16,7 +17,7 @@ namespace Minigames.DivingForPictures [Tooltip("Index of the prefab this obstacle was created from")] [SerializeField] private int prefabIndex; - [Tooltip("Movement speed of this obstacle")] + [Tooltip("Movement speed of this obstacle (will be overridden by normalized settings)")] [SerializeField] private float moveSpeed = 2f; [Header("Movement")] @@ -51,6 +52,10 @@ namespace Minigames.DivingForPictures private float _velocityFactor = 1.0f; // Current velocity factor from game manager private float _baseMoveSpeed; // Original move speed before velocity factor is applied + // Screen normalization + private float _screenNormalizationFactor = 1.0f; + private IDivingMinigameSettings _settings; + private void Awake() { _collider = GetComponent(); @@ -66,7 +71,45 @@ namespace Minigames.DivingForPictures } _mainCamera = Camera.main; - _baseMoveSpeed = moveSpeed; // Store original speed + + // Get settings + _settings = GameManager.GetSettingsObject(); + if (_settings == null) + { + Debug.LogWarning("[FloatingObstacle] Could not retrieve settings, using default values"); + _baseMoveSpeed = moveSpeed; // Use the serialized value as fallback + } + else + { + // Initialize with the obstacle-specific normalized speed settings + float minSpeed = _settings.ObstacleMinMoveSpeed; + float maxSpeed = _settings.ObstacleMaxMoveSpeed; + + // For variety, randomly assign a speed between min and max + _baseMoveSpeed = Random.Range(minSpeed, maxSpeed); + Debug.Log($"[FloatingObstacle] Initialized with normalized speed: {_baseMoveSpeed} (range: {minSpeed}-{maxSpeed})"); + } + + // Calculate screen normalization factor + CalculateScreenNormalizationFactor(); + } + + /// + /// Calculates the screen normalization factor based on current screen height + /// + private void CalculateScreenNormalizationFactor() + { + // Get reference height from settings with fallback if not available + float referenceHeight = 1080f; // Default fallback value + + if (_settings != null) + { + referenceHeight = _settings.ReferenceScreenHeight; + } + + // Calculate normalization factor based on screen height + _screenNormalizationFactor = Screen.height / referenceHeight; + Debug.Log($"[FloatingObstacle] Screen normalization factor: {_screenNormalizationFactor} (Screen height: {Screen.height}, Reference: {referenceHeight})"); } private void OnEnable() @@ -119,7 +162,7 @@ namespace Minigames.DivingForPictures // Update actual move speed based on velocity factor and base speed // We use Abs for magnitude and Sign for direction - moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor); + moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor) * _screenNormalizationFactor; // Restart movement with new speed if needed if (enableMovement && gameObject.activeInHierarchy) @@ -131,18 +174,22 @@ namespace Minigames.DivingForPictures _movementCoroutine = StartCoroutine(MovementCoroutine()); } - Debug.Log($"[FloatingObstacle] {gameObject.name} velocity factor updated to {_velocityFactor:F2}, speed: {moveSpeed:F2}"); + Debug.Log($"[FloatingObstacle] {gameObject.name} velocity factor updated to {_velocityFactor:F2}, normalized speed: {moveSpeed:F2}"); } /// - /// Coroutine that handles obstacle movement + /// Coroutine that handles obstacle movement using normalized velocities /// private IEnumerator MovementCoroutine() { + Debug.Log($"[FloatingObstacle] Started movement coroutine with speed: {moveSpeed:F3}"); + while (enabled && gameObject.activeInHierarchy) { // Use velocity factor sign to determine direction Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor); + + // Apply normalized movement with deltaTime for frame rate independence float speed = moveSpeed * Time.deltaTime; // Apply movement in correct direction diff --git a/Assets/Scripts/Minigames/DivingForPictures/Tiles/TrenchTileSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/Tiles/TrenchTileSpawner.cs index 0df5cad4..9d4ba4e0 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Tiles/TrenchTileSpawner.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Tiles/TrenchTileSpawner.cs @@ -56,6 +56,15 @@ namespace Minigames.DivingForPictures // Velocity management private float _baseMoveSpeed; private float _velocityFactor = 1.0f; + + // Coroutine references + private Coroutine _movementCoroutine; + private Coroutine _tileDestructionCoroutine; + private Coroutine _tileSpawningCoroutine; + private Coroutine _speedRampingCoroutine; + + // Screen normalization + private float _screenNormalizationFactor = 1.0f; private void Awake() { @@ -75,7 +84,7 @@ namespace Minigames.DivingForPictures Debug.LogError("[TrenchTileSpawner] Failed to load diving developer settings!"); } - _baseMoveSpeed = _settings?.MoveSpeed ?? 3f; // Store the original base speed + _baseMoveSpeed = _settings?.NormalizedMoveSpeed ?? 3f; // Store the original base speed // Calculate tile heights for each prefab CalculateTileHeights(); @@ -108,8 +117,6 @@ namespace Minigames.DivingForPictures private void Start() { - - // Find DivingGameManager and subscribe to its initialization event DivingGameManager gameManager = FindFirstObjectByType(); if (gameManager != null) @@ -136,23 +143,25 @@ namespace Minigames.DivingForPictures /// private void Initialize() { + // Calculate screen bounds and normalization factor CalculateScreenBounds(); + CalculateScreenNormalizationFactor(); + // Spawn initial tiles to fill the screen SpawnInitialTiles(); - // Initialize velocity and start the velocity calculation coroutine - _currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime; - StartCoroutine(VelocityCalculationRoutine()); + // Initialize velocity and apply screen normalization + _baseMoveSpeed = _settings?.NormalizedMoveSpeed ?? 3f; + _currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime * _screenNormalizationFactor; - Debug.Log("[TrenchTileSpawner] Initialized"); - } - - private void Update() - { - HandleMovement(); - HandleTileDestruction(); - HandleTileSpawning(); - HandleSpeedRamping(); + // Start all coroutines + StartCoroutine(VelocityCalculationRoutine()); + StartMovementCoroutine(); + StartTileDestructionCoroutine(); + StartTileSpawningCoroutine(); + StartSpeedRampingCoroutine(); + + Debug.Log("[TrenchTileSpawner] Initialized with normalized speed"); } /// @@ -315,6 +324,24 @@ namespace Minigames.DivingForPictures _screenTop = top.y; } + /// + /// Calculates the screen normalization factor based on current screen height + /// + private void CalculateScreenNormalizationFactor() + { + // Get reference height from settings with fallback if not available + float referenceHeight = 1080f; // Default fallback value + + if (_settings != null) + { + referenceHeight = _settings.ReferenceScreenHeight; + } + + // Calculate normalization factor based on screen height + _screenNormalizationFactor = Screen.height / referenceHeight; + Debug.Log($"[TrenchTileSpawner] Screen normalization factor: {_screenNormalizationFactor} (Screen height: {Screen.height}, Reference: {referenceHeight})"); + } + /// /// Called when the velocity factor changes from the DivingGameManager /// @@ -324,7 +351,7 @@ namespace Minigames.DivingForPictures // Update the actual move speed based on the velocity factor // This keeps the original move speed intact for game logic - _baseMoveSpeed = _settings.MoveSpeed * Mathf.Abs(_velocityFactor); + _baseMoveSpeed = _settings.NormalizedMoveSpeed * Mathf.Abs(_velocityFactor); // Recalculate velocity immediately CalculateVelocity(); @@ -356,6 +383,55 @@ namespace Minigames.DivingForPictures _stopSpawning = true; } + /// + /// Starts the movement coroutine and stores its reference + /// + private void StartMovementCoroutine() + { + if (_movementCoroutine != null) + { + StopCoroutine(_movementCoroutine); + } + _movementCoroutine = StartCoroutine(MovementCoroutine()); + } + + /// + /// Coroutine that handles obstacle movement using normalized screen-relative speed + /// + private IEnumerator MovementCoroutine() + { + Debug.Log($"[TrenchTileSpawner] Started movement coroutine with normalized speed: {_currentVelocity:F3}"); + + while (enabled && gameObject.activeInHierarchy) + { + // Skip if no active tiles + if (_activeTiles.Count == 0) + { + yield return null; + continue; + } + + // Use velocity factor sign to determine direction + Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor); + + // Apply normalized movement with deltaTime for frame rate independence + float speed = _currentVelocity * _screenNormalizationFactor; + + // Move all active tiles + foreach (var tile in _activeTiles) + { + if (tile != null) + { + // Apply movement in correct direction + tile.transform.position += direction * speed; + } + } + + // Wait for next frame + yield return null; + } + } + /// /// Handles the movement of all active tiles based on the current velocity /// @@ -512,7 +588,7 @@ namespace Minigames.DivingForPictures _speedUpTimer += Time.deltaTime; if (_speedUpTimer >= _settings.SpeedUpInterval) { - _baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxMoveSpeed); + _baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed); _speedUpTimer = 0f; } } @@ -739,5 +815,217 @@ namespace Minigames.DivingForPictures } } } + + /// + /// Starts the tile destruction coroutine and stores its reference + /// + private void StartTileDestructionCoroutine() + { + if (_tileDestructionCoroutine != null) + { + StopCoroutine(_tileDestructionCoroutine); + } + _tileDestructionCoroutine = StartCoroutine(TileDestructionCoroutine()); + } + + /// + /// Coroutine that checks for tiles to destroy periodically + /// + private IEnumerator TileDestructionCoroutine() + { + const float checkInterval = 0.5f; // Check every half second as requested + Debug.Log($"[TrenchTileSpawner] Started tile destruction coroutine with interval: {checkInterval}s"); + + while (enabled && gameObject.activeInHierarchy) + { + // Check and handle tile destruction + if (_activeTiles.Count > 0) + { + GameObject topTile = _activeTiles[0]; + if (topTile == null) + { + _activeTiles.RemoveAt(0); + } + else + { + float tileHeight = GetTileHeight(topTile); + + bool shouldDestroy; + if (_isSurfacing) + { + // When surfacing, destroy tiles at the bottom + shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer; + } + else + { + // When descending, destroy tiles at the top + shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer; + } + + if (shouldDestroy) + { + _activeTiles.RemoveAt(0); + onTileDestroyed?.Invoke(topTile); + + if (_devSettings != null && _devSettings.TrenchTileUseObjectPooling && _tilePool != null) + { + // Find the prefab index for this tile + int prefabIndex = GetPrefabIndex(topTile); + if (prefabIndex >= 0) + { + _tilePool.ReturnTile(topTile, prefabIndex); + } + else + { + Destroy(topTile); + } + } + else + { + Destroy(topTile); + } + } + } + } + + // Wait for the next check interval + yield return new WaitForSeconds(checkInterval); + } + } + + /// + /// Starts the tile spawning coroutine and stores its reference + /// + private void StartTileSpawningCoroutine() + { + if (_tileSpawningCoroutine != null) + { + StopCoroutine(_tileSpawningCoroutine); + } + _tileSpawningCoroutine = StartCoroutine(TileSpawningCoroutine()); + } + + /// + /// Coroutine that checks if new tiles need to be spawned periodically + /// + private IEnumerator TileSpawningCoroutine() + { + const float checkInterval = 0.2f; // Check every half second as requested + Debug.Log($"[TrenchTileSpawner] Started tile spawning coroutine with interval: {checkInterval}s"); + + while (enabled && gameObject.activeInHierarchy) + { + // Check if we need to spawn new tiles + if (_activeTiles.Count == 0) + { + // If we have no active tiles and spawning is stopped, trigger the event + if (_stopSpawning) + { + onLastTileLeft.Invoke(); + } + } + else + { + GameObject bottomTile = _activeTiles[^1]; + if (bottomTile == null) + { + _activeTiles.RemoveAt(_activeTiles.Count - 1); + } + else + { + // Get the tile height once to use in all calculations + float tileHeight = GetTileHeight(bottomTile); + + // If we're in stop spawning mode, check if last tile is leaving + if (_stopSpawning) + { + // Check if this is the last tile, and if it's about to leave the screen + if (_activeTiles.Count == 1) + { + bool isLastTileLeaving; + + if (_isSurfacing) + { + // When surfacing, check if bottom of tile is above top of screen + isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer; + } + else + { + // When descending, check if top of tile is below bottom of screen + isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer; + } + + if (isLastTileLeaving) + { + onLastTileLeft.Invoke(); + } + } + } + else + { + // Normal spawning mode + bool shouldSpawn; + float newY; + + if (_isSurfacing) + { + // When surfacing, spawn new tiles at the top + float topEdge = bottomTile.transform.position.y + tileHeight / 2; + shouldSpawn = topEdge < _screenTop + _settings.TileSpawnBuffer; + newY = bottomTile.transform.position.y + tileHeight; + } + else + { + // When descending, spawn new tiles at the bottom + float bottomEdge = bottomTile.transform.position.y - tileHeight / 2; + shouldSpawn = bottomEdge > _screenBottom - _settings.TileSpawnBuffer; + newY = bottomTile.transform.position.y - tileHeight; + } + + if (shouldSpawn) + { + SpawnTileAtY(newY); + } + } + } + } + + // Wait for the next check interval + yield return new WaitForSeconds(checkInterval); + } + } + + /// + /// Starts the speed ramping coroutine and stores its reference + /// + private void StartSpeedRampingCoroutine() + { + if (_speedRampingCoroutine != null) + { + StopCoroutine(_speedRampingCoroutine); + } + _speedRampingCoroutine = StartCoroutine(SpeedRampingCoroutine()); + } + + /// + /// Coroutine that handles increasing the movement speed over time + /// + private IEnumerator SpeedRampingCoroutine() + { + const float checkInterval = 1.0f; // Check once per second as requested + Debug.Log($"[TrenchTileSpawner] Started speed ramping coroutine with interval: {checkInterval}s"); + + while (enabled && gameObject.activeInHierarchy) + { + // Increase the base move speed up to the maximum + _baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed); + + // Recalculate velocity with the new base speed + CalculateVelocity(); + + // Wait for the next check interval + yield return new WaitForSeconds(checkInterval); + } + } } } diff --git a/Assets/Settings/DivingMinigameSettings.asset b/Assets/Settings/DivingMinigameSettings.asset index 58d56dd8..a484cd4b 100644 --- a/Assets/Settings/DivingMinigameSettings.asset +++ b/Assets/Settings/DivingMinigameSettings.asset @@ -29,19 +29,22 @@ MonoBehaviour: speedTransitionDuration: 2 surfacingSpeedFactor: 3 surfacingSpawnDelay: 5 + referenceScreenHeight: 1920 initialTileCount: 3 tileSpawnBuffer: 1 - moveSpeed: 1 + normalizedTileMoveSpeed: 0.5 speedUpFactor: 0 speedUpInterval: 10 + maxNormalizedTileMoveSpeed: 0.5 + moveSpeed: 1 maxMoveSpeed: 12 velocityCalculationInterval: 0.5 obstacleSpawnInterval: 2 obstacleSpawnIntervalVariation: 0.5 obstacleMaxSpawnAttempts: 10 obstacleSpawnCollisionRadius: 1 - obstacleMinMoveSpeed: 1 - obstacleMaxMoveSpeed: 4 + normalizedObstacleMinMoveSpeed: 1 + normalizedObstacleMaxMoveSpeed: 2 damageImmunityDuration: 1 bumpForce: 5 smoothMoveSpeed: 8