The feel is fine

This commit is contained in:
2025-09-24 15:16:31 +02:00
parent 783541a776
commit aeaa977294
19 changed files with 494 additions and 344 deletions

View File

@@ -31,7 +31,7 @@ MonoBehaviour:
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a9569848f604a6540827d4d4bb0a35c2 - m_GUID: a9569848f604a6540827d4d4bb0a35c2
m_Address: Settings/MinigameSettings m_Address: Settings/DivingMinigameSettings
m_ReadOnly: 0 m_ReadOnly: 0
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0

View File

@@ -47,7 +47,6 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
prefabIndex: 0 prefabIndex: 0
damage: 1
moveSpeed: 2 moveSpeed: 2
enableMovement: 1 enableMovement: 1
spawner: {fileID: 0} spawner: {fileID: 0}

View File

@@ -222,22 +222,4 @@ public class GameManager : MonoBehaviour
} }
return null; return null;
} }
// MINIGAME SETTINGS
// Endless Descender settings
public float EndlessDescenderLerpSpeed => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderLerpSpeed ?? 12f;
public float EndlessDescenderMaxOffset => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderMaxOffset ?? 3f;
public float EndlessDescenderClampXMin => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderClampXMin ?? -3.5f;
public float EndlessDescenderClampXMax => GetSettings<IDivingMinigameSettings>()?.EndlessDescenderClampXMax ?? 3.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;
} }

View File

@@ -2,6 +2,15 @@
namespace AppleHills.Core.Settings namespace AppleHills.Core.Settings
{ {
/// <summary>
/// Enum defining the type of bump response when player collides with obstacles
/// </summary>
public enum BumpMode
{
Impulse = 0,
SmoothToCenter = 1
}
/// <summary> /// <summary>
/// Developer settings for the diving minigame technical configuration. /// Developer settings for the diving minigame technical configuration.
/// These settings are separate from gameplay/design settings and focus on technical implementation details. /// These settings are separate from gameplay/design settings and focus on technical implementation details.
@@ -125,7 +134,7 @@ namespace AppleHills.Core.Settings
[SerializeField] private bool blockInputDuringImmunity = true; [SerializeField] private bool blockInputDuringImmunity = true;
[Tooltip("Type of bump response: 0=Impulse, 1=SmoothToCenter")] [Tooltip("Type of bump response: 0=Impulse, 1=SmoothToCenter")]
[SerializeField] private int bumpMode = 0; [SerializeField] private BumpMode bumpMode = BumpMode.Impulse;
[Tooltip("Animation curve controlling bump movement over time")] [Tooltip("Animation curve controlling bump movement over time")]
[SerializeField] private AnimationCurve bumpCurve = new AnimationCurve( [SerializeField] private AnimationCurve bumpCurve = new AnimationCurve(
@@ -178,7 +187,7 @@ namespace AppleHills.Core.Settings
// Collision Settings properties // Collision Settings properties
public LayerMask PlayerObstacleLayerMask => playerObstacleLayerMask; public LayerMask PlayerObstacleLayerMask => playerObstacleLayerMask;
public bool BlockInputDuringImmunity => blockInputDuringImmunity; public bool BlockInputDuringImmunity => blockInputDuringImmunity;
public int BumpMode => bumpMode; public BumpMode BumpMode => bumpMode;
public AnimationCurve BumpCurve => bumpCurve; public AnimationCurve BumpCurve => bumpCurve;
public override void OnValidate() public override void OnValidate()
@@ -231,7 +240,7 @@ namespace AppleHills.Core.Settings
playerRotationSmoothing = Mathf.Max(0.1f, playerRotationSmoothing); playerRotationSmoothing = Mathf.Max(0.1f, playerRotationSmoothing);
// Validate Collision settings // Validate Collision settings
bumpMode = Mathf.Clamp(bumpMode, 0, 1); bumpMode = (BumpMode)Mathf.Clamp((int)bumpMode, 0, 1);
} }
} }
} }

View File

@@ -8,227 +8,227 @@ namespace AppleHills.Core.Settings
[CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)] [CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)]
public class DivingMinigameSettings : BaseSettings, IDivingMinigameSettings public class DivingMinigameSettings : BaseSettings, IDivingMinigameSettings
{ {
[Header("Endless Descender - Basic Movement")] [Header("Basic Movement")]
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")] [Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
[SerializeField] private float endlessDescenderLerpSpeed = 12f; [SerializeField] private float lerpSpeed = 12f;
[Tooltip("Maximum horizontal offset allowed between character and finger position")] [Tooltip("Maximum horizontal offset allowed between character and finger position")]
[SerializeField] private float endlessDescenderMaxOffset = 3f; [SerializeField] private float maxOffset = 3f;
[Tooltip("Minimum allowed X position for endless descender movement")] [Tooltip("Minimum allowed X position for movement")]
[SerializeField] private float endlessDescenderClampXMin = -3.5f; [SerializeField] private float clampXMin = -3.5f;
[Tooltip("Maximum allowed X position for endless descender movement")] [Tooltip("Maximum allowed X position for movement")]
[SerializeField] private float endlessDescenderClampXMax = 3.5f; [SerializeField] private float clampXMax = 3.5f;
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")] [Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
[SerializeField] private float endlessDescenderSpeedExponent = 2.5f; [SerializeField] private float speedExponent = 2.5f;
[Header("Endless Descender - Player Movement")] [Header("Player Movement")]
[Tooltip("Maximum distance the player can move from a single tap")] [Tooltip("Maximum distance the player can move from a single tap")]
[SerializeField] private float endlessDescenderTapMaxDistance = 0.5f; [SerializeField] private float tapMaxDistance = 0.5f;
[Tooltip("How quickly the tap impulse fades (higher = faster stop)")] [Tooltip("How quickly the tap impulse fades (higher = faster stop)")]
[SerializeField] private float endlessDescenderTapDecelerationRate = 5.0f; [SerializeField] private float tapDecelerationRate = 5.0f;
[Header("Endless Descender - Monster Spawning")] [Header("Monster Spawning")]
[Tooltip("Base chance (0-1) of spawning a monster on each tile")] [Tooltip("Base chance (0-1) of spawning a monster on each tile")]
[SerializeField] private float endlessDescenderBaseSpawnProbability = 0.2f; [SerializeField] private float baseSpawnProbability = 0.2f;
[Tooltip("Maximum chance (0-1) of spawning a monster")] [Tooltip("Maximum chance (0-1) of spawning a monster")]
[SerializeField] private float endlessDescenderMaxSpawnProbability = 0.5f; [SerializeField] private float maxSpawnProbability = 0.5f;
[Tooltip("How fast the probability increases per second")] [Tooltip("How fast the probability increases per second")]
[SerializeField] private float endlessDescenderProbabilityIncreaseRate = 0.01f; [SerializeField] private float probabilityIncreaseRate = 0.01f;
[Tooltip("Force a spawn after this many seconds without spawns")] [Tooltip("Force a spawn after this many seconds without spawns")]
[SerializeField] private float endlessDescenderGuaranteedSpawnTime = 30f; [SerializeField] private float guaranteedSpawnTime = 30f;
[Tooltip("Minimum time between monster spawns")] [Tooltip("Minimum time between monster spawns")]
[SerializeField] private float endlessDescenderSpawnCooldown = 5f; [SerializeField] private float spawnCooldown = 5f;
[Header("Endless Descender - Scoring")] [Header("Scoring")]
[Tooltip("Base points for taking a picture")] [Tooltip("Base points for taking a picture")]
[SerializeField] private int endlessDescenderBasePoints = 100; [SerializeField] private int basePoints = 100;
[Tooltip("Additional points per depth unit")] [Tooltip("Additional points per depth unit")]
[SerializeField] private int endlessDescenderDepthMultiplier = 10; [SerializeField] private int depthMultiplier = 10;
[Header("Endless Descender - Surfacing")] [Header("Surfacing")]
[Tooltip("Duration in seconds for speed transition when surfacing")] [Tooltip("Duration in seconds for speed transition when surfacing")]
[SerializeField] private float endlessDescenderSpeedTransitionDuration = 2.0f; [SerializeField] private float speedTransitionDuration = 2.0f;
[Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")] [Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
[SerializeField] private float endlessDescenderSurfacingSpeedFactor = 3.0f; [SerializeField] private float surfacingSpeedFactor = 3.0f;
[Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")] [Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
[SerializeField] private float endlessDescenderSurfacingSpawnDelay = 5.0f; [SerializeField] private float surfacingSpawnDelay = 5.0f;
[Header("Endless Descender - Tile Generation")] [Header("Tile Generation")]
[Tooltip("Initial number of tiles to create at start")] [Tooltip("Initial number of tiles to create at start")]
[SerializeField] private int endlessDescenderInitialTileCount = 3; [SerializeField] private int initialTileCount = 3;
[Tooltip("Buffer distance for spawning new tiles")] [Tooltip("Buffer distance for spawning new tiles")]
[SerializeField] private float endlessDescenderTileSpawnBuffer = 1f; [SerializeField] private float tileSpawnBuffer = 1f;
[Tooltip("Base movement speed for tiles")] [Tooltip("Base movement speed for tiles")]
[SerializeField] private float endlessDescenderMoveSpeed = 3f; [SerializeField] private float moveSpeed = 3f;
[Tooltip("Factor to increase speed by each interval")] [Tooltip("Factor to increase speed by each interval")]
[SerializeField] private float endlessDescenderSpeedUpFactor = 0.2f; [SerializeField] private float speedUpFactor = 0.2f;
[Tooltip("Time interval between speed increases (seconds)")] [Tooltip("Time interval between speed increases (seconds)")]
[SerializeField] private float endlessDescenderSpeedUpInterval = 10f; [SerializeField] private float speedUpInterval = 10f;
[Tooltip("Maximum movement speed allowed")] [Tooltip("Maximum movement speed allowed")]
[SerializeField] private float endlessDescenderMaxMoveSpeed = 12f; [SerializeField] private float maxMoveSpeed = 12f;
[Tooltip("Interval for velocity calculations (seconds)")] [Tooltip("Interval for velocity calculations (seconds)")]
[SerializeField] private float endlessDescenderVelocityCalculationInterval = 0.5f; [SerializeField] private float velocityCalculationInterval = 0.5f;
[Header("Endless Descender - Obstacles")] [Header("Obstacles")]
[Tooltip("Time interval between obstacle spawn attempts (in seconds)")] [Tooltip("Time interval between obstacle spawn attempts (in seconds)")]
[SerializeField] private float endlessDescenderObstacleSpawnInterval = 2f; [SerializeField] private float obstacleSpawnInterval = 2f;
[Tooltip("Random variation in obstacle spawn timing (+/- seconds)")] [Tooltip("Random variation in obstacle spawn timing (+/- seconds)")]
[SerializeField] private float endlessDescenderObstacleSpawnIntervalVariation = 0.5f; [SerializeField] private float obstacleSpawnIntervalVariation = 0.5f;
[Tooltip("Maximum number of obstacle spawn position attempts before skipping")] [Tooltip("Maximum number of obstacle spawn position attempts before skipping")]
[SerializeField] private int endlessDescenderObstacleMaxSpawnAttempts = 10; [SerializeField] private int obstacleMaxSpawnAttempts = 10;
[Tooltip("Radius around obstacle spawn point to check for tile collisions")] [Tooltip("Radius around obstacle spawn point to check for tile collisions")]
[SerializeField] private float endlessDescenderObstacleSpawnCollisionRadius = 1f; [SerializeField] private float obstacleSpawnCollisionRadius = 1f;
[Tooltip("Minimum movement speed for spawned obstacles")] [Tooltip("Minimum movement speed for spawned obstacles")]
[SerializeField] private float endlessDescenderObstacleMinMoveSpeed = 1f; [SerializeField] private float obstacleMinMoveSpeed = 1f;
[Tooltip("Maximum movement speed for spawned obstacles")] [Tooltip("Maximum movement speed for spawned obstacles")]
[SerializeField] private float endlessDescenderObstacleMaxMoveSpeed = 4f; [SerializeField] private float obstacleMaxMoveSpeed = 4f;
[Header("Endless Descender - Collision Handling")] [Header("Collision Handling")]
[Tooltip("Duration in seconds of damage immunity after being hit")] [Tooltip("Duration in seconds of damage immunity after being hit")]
[SerializeField] private float endlessDescenderDamageImmunityDuration = 1.0f; [SerializeField] private float damageImmunityDuration = 1.0f;
[Tooltip("Force strength for impulse bumps - higher values push further toward center")] [Tooltip("Force strength for impulse bumps - higher values push further toward center")]
[SerializeField] private float endlessDescenderBumpForce = 5.0f; [SerializeField] private float bumpForce = 5.0f;
[Tooltip("Speed for smooth movement to center (units per second)")] [Tooltip("Speed for smooth movement to center (units per second)")]
[SerializeField] private float endlessDescenderSmoothMoveSpeed = 8.0f; [SerializeField] private float smoothMoveSpeed = 8.0f;
[Tooltip("Whether to block player input during bump movement")] [Tooltip("Whether to block player input during bump movement")]
[SerializeField] private bool endlessDescenderBlockInputDuringBump = true; [SerializeField] private bool blockInputDuringBump = true;
// IMinigameSettings implementation - Basic Movement // IDivingMinigameSettings implementation - Basic Movement
public float EndlessDescenderLerpSpeed => endlessDescenderLerpSpeed; public float LerpSpeed => lerpSpeed;
public float EndlessDescenderMaxOffset => endlessDescenderMaxOffset; public float MaxOffset => maxOffset;
public float EndlessDescenderClampXMin => endlessDescenderClampXMin; public float ClampXMin => clampXMin;
public float EndlessDescenderClampXMax => endlessDescenderClampXMax; public float ClampXMax => clampXMax;
public float EndlessDescenderSpeedExponent => endlessDescenderSpeedExponent; public float SpeedExponent => speedExponent;
// IMinigameSettings implementation - Player Movement // IDivingMinigameSettings implementation - Player Movement
public float EndlessDescenderTapMaxDistance => endlessDescenderTapMaxDistance; public float TapMaxDistance => tapMaxDistance;
public float EndlessDescenderTapDecelerationRate => endlessDescenderTapDecelerationRate; public float TapDecelerationRate => tapDecelerationRate;
// IMinigameSettings implementation - Monster Spawning // IDivingMinigameSettings implementation - Monster Spawning
public float EndlessDescenderBaseSpawnProbability => endlessDescenderBaseSpawnProbability; public float BaseSpawnProbability => baseSpawnProbability;
public float EndlessDescenderMaxSpawnProbability => endlessDescenderMaxSpawnProbability; public float MaxSpawnProbability => maxSpawnProbability;
public float EndlessDescenderProbabilityIncreaseRate => endlessDescenderProbabilityIncreaseRate; public float ProbabilityIncreaseRate => probabilityIncreaseRate;
public float EndlessDescenderGuaranteedSpawnTime => endlessDescenderGuaranteedSpawnTime; public float GuaranteedSpawnTime => guaranteedSpawnTime;
public float EndlessDescenderSpawnCooldown => endlessDescenderSpawnCooldown; public float SpawnCooldown => spawnCooldown;
// IMinigameSettings implementation - Scoring // IDivingMinigameSettings implementation - Scoring
public int EndlessDescenderBasePoints => endlessDescenderBasePoints; public int BasePoints => basePoints;
public int EndlessDescenderDepthMultiplier => endlessDescenderDepthMultiplier; public int DepthMultiplier => depthMultiplier;
// IMinigameSettings implementation - Surfacing // IDivingMinigameSettings implementation - Surfacing
public float EndlessDescenderSpeedTransitionDuration => endlessDescenderSpeedTransitionDuration; public float SpeedTransitionDuration => speedTransitionDuration;
public float EndlessDescenderSurfacingSpeedFactor => endlessDescenderSurfacingSpeedFactor; public float SurfacingSpeedFactor => surfacingSpeedFactor;
public float EndlessDescenderSurfacingSpawnDelay => endlessDescenderSurfacingSpawnDelay; public float SurfacingSpawnDelay => surfacingSpawnDelay;
// IMinigameSettings implementation - Tile Generation // IDivingMinigameSettings implementation - Tile Generation
public int EndlessDescenderInitialTileCount => endlessDescenderInitialTileCount; public int InitialTileCount => initialTileCount;
public float EndlessDescenderTileSpawnBuffer => endlessDescenderTileSpawnBuffer; public float TileSpawnBuffer => tileSpawnBuffer;
public float EndlessDescenderMoveSpeed => endlessDescenderMoveSpeed; public float MoveSpeed => moveSpeed;
public float EndlessDescenderSpeedUpFactor => endlessDescenderSpeedUpFactor; public float SpeedUpFactor => speedUpFactor;
public float EndlessDescenderSpeedUpInterval => endlessDescenderSpeedUpInterval; public float SpeedUpInterval => speedUpInterval;
public float EndlessDescenderMaxMoveSpeed => endlessDescenderMaxMoveSpeed; public float MaxMoveSpeed => maxMoveSpeed;
public float EndlessDescenderVelocityCalculationInterval => endlessDescenderVelocityCalculationInterval; public float VelocityCalculationInterval => velocityCalculationInterval;
// IMinigameSettings implementation - Obstacles // IDivingMinigameSettings implementation - Obstacles
public float EndlessDescenderObstacleSpawnInterval => endlessDescenderObstacleSpawnInterval; public float ObstacleSpawnInterval => obstacleSpawnInterval;
public float EndlessDescenderObstacleSpawnIntervalVariation => endlessDescenderObstacleSpawnIntervalVariation; public float ObstacleSpawnIntervalVariation => obstacleSpawnIntervalVariation;
public int EndlessDescenderObstacleMaxSpawnAttempts => endlessDescenderObstacleMaxSpawnAttempts; public int ObstacleMaxSpawnAttempts => obstacleMaxSpawnAttempts;
public float EndlessDescenderObstacleSpawnCollisionRadius => endlessDescenderObstacleSpawnCollisionRadius; public float ObstacleSpawnCollisionRadius => obstacleSpawnCollisionRadius;
public float EndlessDescenderObstacleMinMoveSpeed => endlessDescenderObstacleMinMoveSpeed; public float ObstacleMinMoveSpeed => obstacleMinMoveSpeed;
public float EndlessDescenderObstacleMaxMoveSpeed => endlessDescenderObstacleMaxMoveSpeed; public float ObstacleMaxMoveSpeed => obstacleMaxMoveSpeed;
// IMinigameSettings implementation - Collision Handling // IDivingMinigameSettings implementation - Collision Handling
public float EndlessDescenderDamageImmunityDuration => endlessDescenderDamageImmunityDuration; public float DamageImmunityDuration => damageImmunityDuration;
public float EndlessDescenderBumpForce => endlessDescenderBumpForce; public float BumpForce => bumpForce;
public float EndlessDescenderSmoothMoveSpeed => endlessDescenderSmoothMoveSpeed; public float SmoothMoveSpeed => smoothMoveSpeed;
public bool EndlessDescenderBlockInputDuringBump => endlessDescenderBlockInputDuringBump; public bool BlockInputDuringBump => blockInputDuringBump;
public override void OnValidate() public override void OnValidate()
{ {
base.OnValidate(); base.OnValidate();
// Validate basic movement values // Validate basic movement values
endlessDescenderLerpSpeed = Mathf.Max(0.1f, endlessDescenderLerpSpeed); lerpSpeed = Mathf.Max(0.1f, lerpSpeed);
endlessDescenderMaxOffset = Mathf.Max(0.1f, endlessDescenderMaxOffset); maxOffset = Mathf.Max(0.1f, maxOffset);
endlessDescenderSpeedExponent = Mathf.Max(0.1f, endlessDescenderSpeedExponent); speedExponent = Mathf.Max(0.1f, speedExponent);
// Ensure min is less than max for clamping // Ensure min is less than max for clamping
if (endlessDescenderClampXMin >= endlessDescenderClampXMax) if (clampXMin >= clampXMax)
{ {
endlessDescenderClampXMin = endlessDescenderClampXMax - 0.1f; clampXMin = clampXMax - 0.1f;
} }
// Validate player movement // Validate player movement
endlessDescenderTapMaxDistance = Mathf.Max(0.01f, endlessDescenderTapMaxDistance); tapMaxDistance = Mathf.Max(0.01f, tapMaxDistance);
endlessDescenderTapDecelerationRate = Mathf.Max(0.1f, endlessDescenderTapDecelerationRate); tapDecelerationRate = Mathf.Max(0.1f, tapDecelerationRate);
// Validate probability values // Validate probability values
endlessDescenderBaseSpawnProbability = Mathf.Clamp01(endlessDescenderBaseSpawnProbability); baseSpawnProbability = Mathf.Clamp01(baseSpawnProbability);
endlessDescenderMaxSpawnProbability = Mathf.Clamp01(endlessDescenderMaxSpawnProbability); maxSpawnProbability = Mathf.Clamp01(maxSpawnProbability);
endlessDescenderProbabilityIncreaseRate = Mathf.Max(0f, endlessDescenderProbabilityIncreaseRate); probabilityIncreaseRate = Mathf.Max(0f, probabilityIncreaseRate);
// Ensure max probability is at least base probability // Ensure max probability is at least base probability
if (endlessDescenderMaxSpawnProbability < endlessDescenderBaseSpawnProbability) if (maxSpawnProbability < baseSpawnProbability)
{ {
endlessDescenderMaxSpawnProbability = endlessDescenderBaseSpawnProbability; maxSpawnProbability = baseSpawnProbability;
} }
// Validate time values // Validate time values
endlessDescenderGuaranteedSpawnTime = Mathf.Max(0.1f, endlessDescenderGuaranteedSpawnTime); guaranteedSpawnTime = Mathf.Max(0.1f, guaranteedSpawnTime);
endlessDescenderSpawnCooldown = Mathf.Max(0.1f, endlessDescenderSpawnCooldown); spawnCooldown = Mathf.Max(0.1f, spawnCooldown);
endlessDescenderSpeedTransitionDuration = Mathf.Max(0.1f, endlessDescenderSpeedTransitionDuration); speedTransitionDuration = Mathf.Max(0.1f, speedTransitionDuration);
endlessDescenderSurfacingSpawnDelay = Mathf.Max(0f, endlessDescenderSurfacingSpawnDelay); surfacingSpawnDelay = Mathf.Max(0f, surfacingSpawnDelay);
// Validate scoring // Validate scoring
endlessDescenderBasePoints = Mathf.Max(0, endlessDescenderBasePoints); basePoints = Mathf.Max(0, basePoints);
endlessDescenderDepthMultiplier = Mathf.Max(0, endlessDescenderDepthMultiplier); depthMultiplier = Mathf.Max(0, depthMultiplier);
// Validate tile generation // Validate tile generation
endlessDescenderInitialTileCount = Mathf.Max(1, endlessDescenderInitialTileCount); initialTileCount = Mathf.Max(1, initialTileCount);
endlessDescenderTileSpawnBuffer = Mathf.Max(0f, endlessDescenderTileSpawnBuffer); tileSpawnBuffer = Mathf.Max(0f, tileSpawnBuffer);
endlessDescenderMoveSpeed = Mathf.Max(0.1f, endlessDescenderMoveSpeed); moveSpeed = Mathf.Max(0.1f, moveSpeed);
endlessDescenderSpeedUpFactor = Mathf.Max(0f, endlessDescenderSpeedUpFactor); speedUpFactor = Mathf.Max(0f, speedUpFactor);
endlessDescenderSpeedUpInterval = Mathf.Max(0.1f, endlessDescenderSpeedUpInterval); speedUpInterval = Mathf.Max(0.1f, speedUpInterval);
endlessDescenderMaxMoveSpeed = Mathf.Max(endlessDescenderMoveSpeed, endlessDescenderMaxMoveSpeed); maxMoveSpeed = Mathf.Max(moveSpeed, maxMoveSpeed);
endlessDescenderVelocityCalculationInterval = Mathf.Max(0.01f, endlessDescenderVelocityCalculationInterval); velocityCalculationInterval = Mathf.Max(0.01f, velocityCalculationInterval);
// Validate obstacle values // Validate obstacle values
endlessDescenderObstacleSpawnInterval = Mathf.Max(0.1f, endlessDescenderObstacleSpawnInterval); obstacleSpawnInterval = Mathf.Max(0.1f, obstacleSpawnInterval);
endlessDescenderObstacleSpawnIntervalVariation = Mathf.Max(0f, endlessDescenderObstacleSpawnIntervalVariation); obstacleSpawnIntervalVariation = Mathf.Max(0f, obstacleSpawnIntervalVariation);
endlessDescenderObstacleMaxSpawnAttempts = Mathf.Max(1, endlessDescenderObstacleMaxSpawnAttempts); obstacleMaxSpawnAttempts = Mathf.Max(1, obstacleMaxSpawnAttempts);
endlessDescenderObstacleSpawnCollisionRadius = Mathf.Max(0.1f, endlessDescenderObstacleSpawnCollisionRadius); obstacleSpawnCollisionRadius = Mathf.Max(0.1f, obstacleSpawnCollisionRadius);
endlessDescenderObstacleMinMoveSpeed = Mathf.Max(0.1f, endlessDescenderObstacleMinMoveSpeed); obstacleMinMoveSpeed = Mathf.Max(0.1f, obstacleMinMoveSpeed);
endlessDescenderObstacleMaxMoveSpeed = Mathf.Max(endlessDescenderObstacleMinMoveSpeed, endlessDescenderObstacleMaxMoveSpeed); obstacleMaxMoveSpeed = Mathf.Max(obstacleMinMoveSpeed, obstacleMaxMoveSpeed);
// Validate collision settings // Validate collision settings
endlessDescenderDamageImmunityDuration = Mathf.Max(0.1f, endlessDescenderDamageImmunityDuration); damageImmunityDuration = Mathf.Max(0.1f, damageImmunityDuration);
endlessDescenderBumpForce = Mathf.Max(0.1f, endlessDescenderBumpForce); bumpForce = Mathf.Max(0.1f, bumpForce);
endlessDescenderSmoothMoveSpeed = Mathf.Max(0.1f, endlessDescenderSmoothMoveSpeed); smoothMoveSpeed = Mathf.Max(0.1f, smoothMoveSpeed);
} }
} }
} }

View File

@@ -45,54 +45,54 @@ namespace AppleHills.Core.Settings
/// </summary> /// </summary>
public interface IDivingMinigameSettings public interface IDivingMinigameSettings
{ {
// Endless Descender settings - Basic Movement // Basic Movement
float EndlessDescenderLerpSpeed { get; } float LerpSpeed { get; }
float EndlessDescenderMaxOffset { get; } float MaxOffset { get; }
float EndlessDescenderClampXMin { get; } float ClampXMin { get; }
float EndlessDescenderClampXMax { get; } float ClampXMax { get; }
float EndlessDescenderSpeedExponent { get; } float SpeedExponent { get; }
// Endless Descender - Player Movement // Player Movement
float EndlessDescenderTapMaxDistance { get; } float TapMaxDistance { get; }
float EndlessDescenderTapDecelerationRate { get; } float TapDecelerationRate { get; }
// Endless Descender - Monster Spawning // Monster Spawning
float EndlessDescenderBaseSpawnProbability { get; } float BaseSpawnProbability { get; }
float EndlessDescenderMaxSpawnProbability { get; } float MaxSpawnProbability { get; }
float EndlessDescenderProbabilityIncreaseRate { get; } float ProbabilityIncreaseRate { get; }
float EndlessDescenderGuaranteedSpawnTime { get; } float GuaranteedSpawnTime { get; }
float EndlessDescenderSpawnCooldown { get; } float SpawnCooldown { get; }
// Endless Descender - Scoring // Scoring
int EndlessDescenderBasePoints { get; } int BasePoints { get; }
int EndlessDescenderDepthMultiplier { get; } int DepthMultiplier { get; }
// Endless Descender - Surfacing // Surfacing
float EndlessDescenderSpeedTransitionDuration { get; } float SpeedTransitionDuration { get; }
float EndlessDescenderSurfacingSpeedFactor { get; } float SurfacingSpeedFactor { get; }
float EndlessDescenderSurfacingSpawnDelay { get; } float SurfacingSpawnDelay { get; }
// Endless Descender - Tile Generation // Tile Generation
int EndlessDescenderInitialTileCount { get; } int InitialTileCount { get; }
float EndlessDescenderTileSpawnBuffer { get; } float TileSpawnBuffer { get; }
float EndlessDescenderMoveSpeed { get; } float MoveSpeed { get; }
float EndlessDescenderSpeedUpFactor { get; } float SpeedUpFactor { get; }
float EndlessDescenderSpeedUpInterval { get; } float SpeedUpInterval { get; }
float EndlessDescenderMaxMoveSpeed { get; } float MaxMoveSpeed { get; }
float EndlessDescenderVelocityCalculationInterval { get; } float VelocityCalculationInterval { get; }
// Endless Descender - Obstacles // Obstacles
float EndlessDescenderObstacleSpawnInterval { get; } float ObstacleSpawnInterval { get; }
float EndlessDescenderObstacleSpawnIntervalVariation { get; } float ObstacleSpawnIntervalVariation { get; }
int EndlessDescenderObstacleMaxSpawnAttempts { get; } int ObstacleMaxSpawnAttempts { get; }
float EndlessDescenderObstacleSpawnCollisionRadius { get; } float ObstacleSpawnCollisionRadius { get; }
float EndlessDescenderObstacleMinMoveSpeed { get; } float ObstacleMinMoveSpeed { get; }
float EndlessDescenderObstacleMaxMoveSpeed { get; } float ObstacleMaxMoveSpeed { get; }
// Endless Descender - Collision Handling // Collision Handling
float EndlessDescenderDamageImmunityDuration { get; } float DamageImmunityDuration { get; }
float EndlessDescenderBumpForce { get; } float BumpForce { get; }
float EndlessDescenderSmoothMoveSpeed { get; } float SmoothMoveSpeed { get; }
bool EndlessDescenderBlockInputDuringBump { get; } bool BlockInputDuringBump { get; }
} }
} }

View File

@@ -69,7 +69,7 @@ namespace Minigames.DivingForPictures
} }
// Initialize with base probability from settings // Initialize with base probability from settings
currentSpawnProbability = _settings?.EndlessDescenderBaseSpawnProbability ?? 0.2f; currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
} }
private void Start() private void Start()
@@ -104,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 < _settings.EndlessDescenderMaxSpawnProbability) if (currentSpawnProbability < _settings.MaxSpawnProbability)
{ {
currentSpawnProbability += _settings.EndlessDescenderProbabilityIncreaseRate * Time.deltaTime; currentSpawnProbability += _settings.ProbabilityIncreaseRate * Time.deltaTime;
currentSpawnProbability = Mathf.Min(currentSpawnProbability, _settings.EndlessDescenderMaxSpawnProbability); currentSpawnProbability = Mathf.Min(currentSpawnProbability, _settings.MaxSpawnProbability);
// 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)
@@ -127,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 >= _settings.EndlessDescenderGuaranteedSpawnTime; bool forceSpawn = timeSinceLastSpawn >= _settings.GuaranteedSpawnTime;
bool onCooldown = timeSinceLastSpawn < _settings.EndlessDescenderSpawnCooldown; bool onCooldown = timeSinceLastSpawn < _settings.SpawnCooldown;
// Don't spawn if on cooldown, unless forced // Don't spawn if on cooldown, unless forced
if (onCooldown && !forceSpawn) return; if (onCooldown && !forceSpawn) return;
@@ -145,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 = _settings.EndlessDescenderBaseSpawnProbability; currentSpawnProbability = _settings.BaseSpawnProbability;
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability); OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
} }
} }
@@ -190,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) * _settings.EndlessDescenderDepthMultiplier); int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
int pointsAwarded = _settings.EndlessDescenderBasePoints + depthBonus; int pointsAwarded = _settings.BasePoints + depthBonus;
// Add score // Add score
playerScore += pointsAwarded; playerScore += pointsAwarded;
@@ -342,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 * _settings.EndlessDescenderSurfacingSpeedFactor; float targetVelocityFactor = -1.0f * _settings.SurfacingSpeedFactor;
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)
@@ -511,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(_settings.EndlessDescenderSurfacingSpawnDelay); yield return new WaitForSeconds(_settings.SurfacingSpawnDelay);
// 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>();
@@ -580,10 +580,10 @@ namespace Minigames.DivingForPictures
float startFactor = _currentVelocityFactor; float startFactor = _currentVelocityFactor;
float elapsed = 0f; float elapsed = 0f;
while (elapsed < _settings.EndlessDescenderSpeedTransitionDuration) while (elapsed < _settings.SpeedTransitionDuration)
{ {
elapsed += Time.deltaTime; elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / _settings.EndlessDescenderSpeedTransitionDuration); float t = Mathf.Clamp01(elapsed / _settings.SpeedTransitionDuration);
// Smooth step interpolation // Smooth step interpolation
float smoothStep = t * t * (3f - 2f * t); float smoothStep = t * t * (3f - 2f * t);

View File

@@ -221,9 +221,9 @@ namespace Minigames.DivingForPictures
while (true) while (true)
{ {
// Calculate next spawn time with variation // Calculate next spawn time with variation
float nextSpawnTime = _settings.EndlessDescenderObstacleSpawnInterval + float nextSpawnTime = _settings.ObstacleSpawnInterval +
Random.Range(-_settings.EndlessDescenderObstacleSpawnIntervalVariation, Random.Range(-_settings.ObstacleSpawnIntervalVariation,
_settings.EndlessDescenderObstacleSpawnIntervalVariation); _settings.ObstacleSpawnIntervalVariation);
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);
@@ -257,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 < _settings.EndlessDescenderObstacleMaxSpawnAttempts; attempts++) for (int attempts = 0; attempts < _settings.ObstacleMaxSpawnAttempts; attempts++)
{ {
spawnPosition = GetRandomSpawnPosition(); spawnPosition = GetRandomSpawnPosition();
@@ -270,13 +270,13 @@ namespace Minigames.DivingForPictures
} }
else else
{ {
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{_settings.EndlessDescenderObstacleMaxSpawnAttempts})"); Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{_settings.ObstacleMaxSpawnAttempts})");
} }
} }
if (!foundValidPosition) if (!foundValidPosition)
{ {
Debug.LogWarning($"[ObstacleSpawner] SPAWN MISSED: Could not find valid spawn position after {_settings.EndlessDescenderObstacleMaxSpawnAttempts} attempts at {Time.time:F2}"); Debug.LogWarning($"[ObstacleSpawner] SPAWN MISSED: Could not find valid spawn position after {_settings.ObstacleMaxSpawnAttempts} attempts at {Time.time:F2}");
} }
} }
@@ -300,7 +300,7 @@ namespace Minigames.DivingForPictures
{ {
// Use OverlapCircle to check for collisions with tiles using just the layer // Use OverlapCircle to check for collisions with tiles using just the layer
// Convert the single layer to a layer mask inline (1 << layerNumber) // Convert the single layer to a layer mask inline (1 << layerNumber)
Collider2D collision = Physics2D.OverlapCircle(position, _settings.EndlessDescenderObstacleSpawnCollisionRadius, 1 << _devSettings.TrenchTileLayer); Collider2D collision = Physics2D.OverlapCircle(position, _settings.ObstacleSpawnCollisionRadius, 1 << _devSettings.TrenchTileLayer);
return collision == null; return collision == null;
} }
@@ -412,8 +412,8 @@ namespace Minigames.DivingForPictures
// Randomize properties using settings // Randomize properties using settings
obstacleComponent.MoveSpeed = Random.Range( obstacleComponent.MoveSpeed = Random.Range(
_settings.EndlessDescenderObstacleMinMoveSpeed, _settings.ObstacleMinMoveSpeed,
_settings.EndlessDescenderObstacleMaxMoveSpeed); _settings.ObstacleMaxMoveSpeed);
// 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);
@@ -544,7 +544,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, _settings.EndlessDescenderObstacleSpawnCollisionRadius); Gizmos.DrawWireSphere(center, _settings.ObstacleSpawnCollisionRadius);
} }
} }
#endif #endif

View File

@@ -28,6 +28,14 @@ namespace Minigames.DivingForPictures
protected override void HandleCollisionResponse(Collider2D obstacle) protected override void HandleCollisionResponse(Collider2D obstacle)
{ {
// Check if the obstacle is on the ObstacleLayer
if (obstacle.gameObject.layer != _devSettings.ObstacleLayer)
{
// If not on the obstacle layer, don't process the collision
Debug.Log($"[ObstacleCollision] Ignored collision with object on layer {obstacle.gameObject.layer} (expected {_devSettings.ObstacleLayer})");
return;
}
// Mark the obstacle as having dealt damage to prevent multiple hits // Mark the obstacle as having dealt damage to prevent multiple hits
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>(); FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
if (obstacleComponent != null) if (obstacleComponent != null)
@@ -43,7 +51,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void HandleImmunityStarted() private void HandleImmunityStarted()
{ {
Debug.Log($"[ObstacleCollision] Damage immunity started for {_gameSettings.EndlessDescenderDamageImmunityDuration} seconds"); Debug.Log($"[ObstacleCollision] Damage immunity started for {_gameSettings.DamageImmunityDuration} seconds");
// Don't block input for obstacle damage - let player keep moving // Don't block input for obstacle damage - let player keep moving
// The shared immunity system will handle the collision prevention // The shared immunity system will handle the collision prevention

View File

@@ -2,6 +2,7 @@
using System; using System;
using System.Collections; using System.Collections;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using AppleHills.Utilities;
namespace Minigames.DivingForPictures namespace Minigames.DivingForPictures
{ {
@@ -27,6 +28,7 @@ namespace Minigames.DivingForPictures
private static Coroutine _globalImmunityCoroutine; private static Coroutine _globalImmunityCoroutine;
private static MonoBehaviour _coroutineRunner; private static MonoBehaviour _coroutineRunner;
private static Collider2D _sharedPlayerCollider; private static Collider2D _sharedPlayerCollider;
private static bool wasInputBlocked = false; // Track if input was blocked
// Events for immunity and damage state changes // Events for immunity and damage state changes
public static event Action OnImmunityStarted; public static event Action OnImmunityStarted;
@@ -117,8 +119,8 @@ namespace Minigames.DivingForPictures
if (_isGloballyImmune) if (_isGloballyImmune)
return; return;
// Check if the collider is an obstacle // Use our extension method to check if the collider's layer is in the obstacle layer mask
if ((_devSettings.PlayerObstacleLayerMask.value & (1 << other.gameObject.layer)) != 0) if (_devSettings.PlayerObstacleLayerMask.Contains(other.gameObject))
{ {
HandleObstacleCollision(other); HandleObstacleCollision(other);
} }
@@ -179,6 +181,8 @@ namespace Minigames.DivingForPictures
if (_devSettings.BlockInputDuringImmunity && playerController != null) if (_devSettings.BlockInputDuringImmunity && playerController != null)
{ {
// Notify player controller to block input // Notify player controller to block input
BlockPlayerInput();
wasInputBlocked = true;
} }
// Trigger event for all listeners // Trigger event for all listeners
@@ -200,13 +204,57 @@ namespace Minigames.DivingForPictures
private IEnumerator ImmunityTimerCoroutine() private IEnumerator ImmunityTimerCoroutine()
{ {
// Wait for the immunity duration // Wait for the immunity duration
yield return new WaitForSeconds(_gameSettings.EndlessDescenderDamageImmunityDuration); yield return new WaitForSeconds(_gameSettings.DamageImmunityDuration);
// Reset immunity state // Reset immunity state
_isGloballyImmune = false; _isGloballyImmune = false;
// Restore player input if it was blocked
if (_devSettings.BlockInputDuringImmunity)
{
RestorePlayerInput();
}
// Trigger event for all listeners // Trigger event for all listeners
OnImmunityEnded?.Invoke(); OnImmunityEnded?.Invoke();
} }
/// <summary>
/// Blocks player input during immunity
/// </summary>
protected virtual void BlockPlayerInput()
{
if (playerController != null && playerController.enabled)
{
playerController.enabled = false;
wasInputBlocked = true;
Debug.Log($"[{GetType().Name}] Player input blocked during immunity");
}
}
/// <summary>
/// Restores player input after immunity
/// </summary>
protected virtual void RestorePlayerInput()
{
if (playerController != null && wasInputBlocked)
{
playerController.enabled = true;
wasInputBlocked = false;
// Update the controller's target position to current position to prevent snapping
UpdateControllerTarget();
Debug.Log($"[{GetType().Name}] Player input restored after immunity");
}
}
/// <summary>
/// Updates the player controller's target position to the current position to prevent snapping
/// </summary>
protected virtual void UpdateControllerTarget()
{
// This would normally be implemented in derived classes if needed
}
} }
} }

View File

@@ -47,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, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax); float targetX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
// 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);
@@ -68,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, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax); _targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
_isTouchActive = true; _isTouchActive = true;
} }
@@ -78,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, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax); _targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
} }
/// <summary> /// <summary>
@@ -96,9 +96,9 @@ namespace Minigames.DivingForPictures
if (_isTouchActive) if (_isTouchActive)
{ {
float currentX = transform.position.x; float currentX = transform.position.x;
float lerpSpeed = _settings.EndlessDescenderLerpSpeed; float lerpSpeed = _settings.LerpSpeed;
float maxOffset = _settings.EndlessDescenderMaxOffset; float maxOffset = _settings.MaxOffset;
float exponent = _settings.EndlessDescenderSpeedExponent; float exponent = _settings.SpeedExponent;
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);
@@ -108,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, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax); newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
UpdatePosition(newX); UpdatePosition(newX);
} }
@@ -116,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 = _settings.EndlessDescenderMaxOffset; float maxOffset = _settings.MaxOffset;
float lerpSpeed = _settings.EndlessDescenderLerpSpeed; float lerpSpeed = _settings.LerpSpeed;
// 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, _settings.EndlessDescenderTapMaxDistance * _tapImpulseStrength); moveDistance = Mathf.Min(moveDistance, _settings.TapMaxDistance * _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, _settings.EndlessDescenderClampXMin, _settings.EndlessDescenderClampXMax); newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
// Reduce impulse strength over time // Reduce impulse strength over time
_tapImpulseStrength -= Time.deltaTime * _settings.EndlessDescenderTapDecelerationRate; _tapImpulseStrength -= Time.deltaTime * _settings.TapDecelerationRate;
if (_tapImpulseStrength < 0.01f) if (_tapImpulseStrength < 0.01f)
{ {
_tapImpulseStrength = 0f; _tapImpulseStrength = 0f;

View File

@@ -12,157 +12,139 @@ namespace Minigames.DivingForPictures
{ {
private bool _isBumping; private bool _isBumping;
private Coroutine _bumpCoroutine; private Coroutine _bumpCoroutine;
private bool _bumpInputBlocked; // Tracks bump-specific input blocking
protected override void HandleCollisionResponse(Collider2D obstacle) protected override void HandleCollisionResponse(Collider2D obstacle)
{ {
// Check if the obstacle is on the TrenchTileLayer
if (obstacle.gameObject.layer != _devSettings.TrenchTileLayer)
{
// If not on the trench tile layer, don't process the collision
Debug.Log($"[TileBumpCollision] Ignored collision with object on layer {obstacle.gameObject.layer} (expected {_devSettings.TrenchTileLayer})");
return;
}
// Use bump mode from developer settings // Use bump mode from developer settings
switch (_devSettings.BumpMode) switch (_devSettings.BumpMode)
{ {
case 0: // Impulse mode case BumpMode.Impulse:
StartImpulseBump(); StartImpulseBump();
break; break;
case 1: // SmoothToCenter mode case BumpMode.SmoothToCenter:
StartSmoothMoveToCenter(); StartSmoothMoveToCenter();
break; break;
} }
Debug.Log($"[TileBumpCollision] Collision handled with {(_devSettings.BumpMode == 0 ? "Impulse" : "SmoothToCenter")} mode"); Debug.Log($"[TileBumpCollision] Collision handled with {_devSettings.BumpMode} mode");
} }
/// <summary> /// <summary>
/// Applies an impulse force toward center /// Starts an impulse bump toward the center with force-based distance
/// </summary> /// </summary>
private void StartImpulseBump() private void StartImpulseBump()
{ {
if (_isBumping || playerCharacter == null) if (playerCharacter == null) return;
return;
_isBumping = true; float currentX = playerCharacter.transform.position.x;
// Block input during bump if configured // Calculate bump distance based on force and current position
if (_gameSettings.EndlessDescenderBlockInputDuringBump && playerController != null) float directionToCenter = currentX > 0 ? -1f : 1f; // Direction toward center
// Calculate target position - closer to center based on bump force
float bumpDistance = _gameSettings.BumpForce * 0.2f; // Scale factor for distance
float targetX = currentX + (directionToCenter * bumpDistance);
// Clamp to center if we would overshoot
if ((currentX > 0 && targetX < 0) || (currentX < 0 && targetX > 0))
{ {
_bumpInputBlocked = true; targetX = 0f;
// TODO: Implement input blocking
} }
// Calculate direction to center (X = 0) float bumpDuration = 0.5f; // Fixed duration for impulse
float directionToCenter = Mathf.Sign(-playerCharacter.transform.position.x);
// Start impulse bump coroutine StartBump(currentX, targetX, bumpDuration);
if (_bumpCoroutine != null)
StopCoroutine(_bumpCoroutine);
_bumpCoroutine = StartCoroutine(ImpulseBumpCoroutine(directionToCenter)); Debug.Log($"[TileBumpCollision] Starting impulse bump from X={currentX} to X={targetX} (force={_gameSettings.BumpForce})");
Debug.Log($"[TileBumpCollision] Started impulse bump with force {_gameSettings.EndlessDescenderBumpForce} in direction {directionToCenter}");
} }
/// <summary> /// <summary>
/// Smoothly moves the player to center /// Starts smooth movement to the center
/// </summary> /// </summary>
private void StartSmoothMoveToCenter() private void StartSmoothMoveToCenter()
{ {
if (_isBumping || playerCharacter == null) if (playerCharacter == null) return;
return;
float currentX = playerCharacter.transform.position.x;
float distanceToCenter = Mathf.Abs(currentX);
float targetX = 0f; // Always move to center
float bumpDuration = distanceToCenter / _gameSettings.SmoothMoveSpeed; // Duration based on distance and speed
StartBump(currentX, targetX, bumpDuration);
Debug.Log($"[TileBumpCollision] Starting smooth move to center from X={currentX} (speed={_gameSettings.SmoothMoveSpeed}, duration={bumpDuration:F2}s)");
}
/// <summary>
/// Common bump initialization using coroutines
/// </summary>
private void StartBump(float startX, float targetX, float duration)
{
// Stop any existing bump
if (_bumpCoroutine != null)
{
StopCoroutine(_bumpCoroutine);
_bumpCoroutine = null;
}
_isBumping = true; _isBumping = true;
// Block input during bump if configured // Start bump coroutine
if (_gameSettings.EndlessDescenderBlockInputDuringBump && playerController != null) _bumpCoroutine = StartCoroutine(BumpCoroutine(startX, targetX, duration));
{
_bumpInputBlocked = true;
// TODO: Implement input blocking
}
// Start smooth move coroutine
if (_bumpCoroutine != null)
StopCoroutine(_bumpCoroutine);
_bumpCoroutine = StartCoroutine(SmoothMoveToCenterCoroutine());
Debug.Log($"[TileBumpCollision] Started smooth move to center with speed {_gameSettings.EndlessDescenderSmoothMoveSpeed}");
} }
/// <summary> /// <summary>
/// Coroutine to handle impulse bump movement /// Coroutine that handles the bump movement over time
/// </summary> /// </summary>
private IEnumerator ImpulseBumpCoroutine(float direction) private IEnumerator BumpCoroutine(float startX, float targetX, float duration)
{ {
float elapsedTime = 0f; float elapsedTime = 0f;
float bumpDuration = 0.5f; // Fixed duration for impulse
Vector3 startPosition = playerCharacter.transform.position;
while (elapsedTime < bumpDuration) while (elapsedTime < duration)
{ {
elapsedTime += Time.deltaTime; elapsedTime += Time.deltaTime;
// Use evaluation time from curve for non-linear movement // Calculate progress and apply curve
float t = elapsedTime / bumpDuration; float progress = elapsedTime / duration;
float curveValue = _devSettings.BumpCurve.Evaluate(t); float curveValue = _devSettings.BumpCurve.Evaluate(progress);
// Calculate movement distance based on force and curve // Interpolate position
float distance = _gameSettings.EndlessDescenderBumpForce * curveValue * Time.deltaTime; float currentX = Mathf.Lerp(startX, targetX, curveValue);
// Move the player toward center // Apply the position to the player character
Vector3 newPosition = playerCharacter.transform.position; if (playerCharacter != null)
newPosition.x += direction * distance; {
Vector3 currentPos = playerCharacter.transform.position;
// Clamp to valid range currentPos.x = Mathf.Clamp(currentX, _gameSettings.ClampXMin, _gameSettings.ClampXMax);
newPosition.x = Mathf.Clamp(newPosition.x, _gameSettings.EndlessDescenderClampXMin, _gameSettings.EndlessDescenderClampXMax); playerCharacter.transform.position = currentPos;
}
// Apply the position
playerCharacter.transform.position = newPosition;
yield return null; yield return null;
} }
// Finish bump // Ensure we end exactly at target
_isBumping = false; if (playerCharacter != null)
_bumpInputBlocked = false;
_bumpCoroutine = null;
}
/// <summary>
/// Coroutine to handle smooth movement to center
/// </summary>
private IEnumerator SmoothMoveToCenterCoroutine()
{ {
Vector3 startPosition = playerCharacter.transform.position; Vector3 currentPos = playerCharacter.transform.position;
Vector3 targetPosition = new Vector3(0f, startPosition.y, startPosition.z); float clampedTargetX = Mathf.Clamp(targetX, _gameSettings.ClampXMin, _gameSettings.ClampXMax);
playerCharacter.transform.position = new Vector3(clampedTargetX, currentPos.y, currentPos.z);
// Calculate distance to center and expected duration
float distanceToCenter = Mathf.Abs(startPosition.x);
float expectedDuration = distanceToCenter / _gameSettings.EndlessDescenderSmoothMoveSpeed;
float elapsedTime = 0f;
// Move until we reach the center
while (elapsedTime < expectedDuration)
{
elapsedTime += Time.deltaTime;
// Calculate progress based on time and curve
float t = elapsedTime / expectedDuration;
float curveValue = _devSettings.BumpCurve.Evaluate(t);
// Calculate interpolated position
Vector3 newPosition = Vector3.Lerp(startPosition, targetPosition, curveValue);
// Apply the position
playerCharacter.transform.position = newPosition;
yield return null;
} }
// Ensure we end at exactly the center // Bump finished
playerCharacter.transform.position = targetPosition;
// Finish bump
_isBumping = false; _isBumping = false;
_bumpInputBlocked = false;
_bumpCoroutine = null; _bumpCoroutine = null;
Debug.Log("[TileBumpCollision] Bump movement completed");
} }
} }
} }

View File

@@ -75,7 +75,7 @@ namespace Minigames.DivingForPictures
Debug.LogError("[TrenchTileSpawner] Failed to load diving developer settings!"); Debug.LogError("[TrenchTileSpawner] Failed to load diving developer settings!");
} }
_baseMoveSpeed = _settings?.EndlessDescenderMoveSpeed ?? 3f; // Store the original base speed _baseMoveSpeed = _settings?.MoveSpeed ?? 3f; // Store the original base speed
// Calculate tile heights for each prefab // Calculate tile heights for each prefab
CalculateTileHeights(); CalculateTileHeights();
@@ -150,7 +150,7 @@ namespace Minigames.DivingForPictures
while (true) while (true)
{ {
CalculateVelocity(); CalculateVelocity();
yield return new WaitForSeconds(_settings.EndlessDescenderVelocityCalculationInterval); yield return new WaitForSeconds(_settings.VelocityCalculationInterval);
} }
} }
@@ -249,7 +249,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 < _settings.EndlessDescenderInitialTileCount; i++) for (int i = 0; i < _settings.InitialTileCount; i++)
{ {
float y = startingY; float y = startingY;
// Calculate proper Y position based on previous tiles // Calculate proper Y position based on previous tiles
@@ -293,7 +293,7 @@ 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
_baseMoveSpeed = _settings.EndlessDescenderMoveSpeed * Mathf.Abs(_velocityFactor); _baseMoveSpeed = _settings.MoveSpeed * Mathf.Abs(_velocityFactor);
// Recalculate velocity immediately // Recalculate velocity immediately
CalculateVelocity(); CalculateVelocity();
@@ -364,12 +364,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 - _settings.EndlessDescenderTileSpawnBuffer; shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer;
} }
else else
{ {
// When descending, destroy tiles at the top // When descending, destroy tiles at the top
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.EndlessDescenderTileSpawnBuffer; shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer;
} }
if (shouldDestroy) if (shouldDestroy)
@@ -433,12 +433,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 + _settings.EndlessDescenderTileSpawnBuffer; isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer;
} }
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 - _settings.EndlessDescenderTileSpawnBuffer; isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer;
} }
if (isLastTileLeaving) if (isLastTileLeaving)
@@ -456,14 +456,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 + _settings.EndlessDescenderTileSpawnBuffer; shouldSpawn = topEdge < _screenTop + _settings.TileSpawnBuffer;
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 - _settings.EndlessDescenderTileSpawnBuffer; shouldSpawn = bottomEdge > _screenBottom - _settings.TileSpawnBuffer;
newY = bottomTile.transform.position.y - tileHeight; newY = bottomTile.transform.position.y - tileHeight;
} }
@@ -479,9 +479,9 @@ namespace Minigames.DivingForPictures
private void HandleSpeedRamping() private void HandleSpeedRamping()
{ {
_speedUpTimer += Time.deltaTime; _speedUpTimer += Time.deltaTime;
if (_speedUpTimer >= _settings.EndlessDescenderSpeedUpInterval) if (_speedUpTimer >= _settings.SpeedUpInterval)
{ {
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.EndlessDescenderSpeedUpFactor, _settings.EndlessDescenderMaxMoveSpeed); _baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxMoveSpeed);
_speedUpTimer = 0f; _speedUpTimer = 0f;
} }
} }
@@ -520,11 +520,25 @@ namespace Minigames.DivingForPictures
tile.transform.position = new Vector3(0f, y, TileSpawnZ); tile.transform.position = new Vector3(0f, y, TileSpawnZ);
tile.transform.rotation = prefab.transform.rotation; tile.transform.rotation = prefab.transform.rotation;
tile.transform.SetParent(transform); tile.transform.SetParent(transform);
// Set the layer to the configured trench tile layer
if (_devSettings != null)
{
tile.layer = _devSettings.TrenchTileLayer;
SetLayerRecursively(tile, _devSettings.TrenchTileLayer);
}
} }
else else
{ {
// Use the prefab's original rotation // Use the prefab's original rotation
tile = Instantiate(prefab, new Vector3(0f, y, TileSpawnZ), prefab.transform.rotation, transform); tile = Instantiate(prefab, new Vector3(0f, y, TileSpawnZ), prefab.transform.rotation, transform);
// Set the layer to the configured trench tile layer
if (_devSettings != null)
{
tile.layer = _devSettings.TrenchTileLayer;
SetLayerRecursively(tile, _devSettings.TrenchTileLayer);
}
} }
_activeTiles.Add(tile); _activeTiles.Add(tile);
@@ -660,7 +674,7 @@ namespace Minigames.DivingForPictures
Gizmos.color = Color.cyan; Gizmos.color = Color.cyan;
if (_settings != null) if (_settings != null)
{ {
for (int i = 0; i < _settings.EndlessDescenderInitialTileCount; i++) for (int i = 0; i < _settings.InitialTileCount; 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 &&
@@ -674,5 +688,25 @@ namespace Minigames.DivingForPictures
} }
} }
#endif #endif
/// <summary>
/// Set the layer of a GameObject and all its children recursively
/// </summary>
/// <param name="obj">The GameObject to set the layer for</param>
/// <param name="layer">The layer index to set</param>
private void SetLayerRecursively(GameObject obj, int layer)
{
if (obj == null) return;
obj.layer = layer;
foreach (Transform child in obj.transform)
{
if (child != null)
{
SetLayerRecursively(child.gameObject, layer);
}
}
}
} }
} }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d54ca063d685467f9cb2c05507ac833f
timeCreated: 1758717247

View File

@@ -0,0 +1,55 @@
using UnityEngine;
namespace AppleHills.Utilities
{
/// <summary>
/// Collection of useful extension methods for Unity built-in classes
/// </summary>
public static class UnityExtensions
{
/// <summary>
/// Extension method to check if a layer is in a layermask.
/// Accounts for Unity's 0-indexed layer system when comparing with editor layer values.
/// </summary>
/// <param name="mask">The layer mask to check</param>
/// <param name="layer">The layer value to check for</param>
/// <returns>True if the layer is in the mask, false otherwise</returns>
public static bool Contains(this LayerMask mask, int layer)
{
// Adjust for the -1 offset as specifically requested
int adjustedLayer = layer - 1;
return mask.value == (mask.value | (1 << adjustedLayer));
}
/// <summary>
/// Extension method to check if a GameObject's layer is in a layermask.
/// Automatically gets the layer from the GameObject and handles the offset.
/// </summary>
/// <param name="mask">The layer mask to check</param>
/// <param name="gameObject">The GameObject whose layer to check</param>
/// <returns>True if the GameObject's layer is in the mask, false otherwise</returns>
public static bool Contains(this LayerMask mask, GameObject gameObject)
{
if (gameObject == null) return false;
int layer = gameObject.layer;
// Adjust for the -1 offset as specifically requested
int adjustedLayer = layer - 1;
return mask.value == (mask.value | (1 << adjustedLayer));
}
/// <summary>
/// Bitwise check if a layer is in a layermask.
/// This is an alternative implementation that uses bitwise AND operation.
/// </summary>
/// <param name="mask">The layer mask to check</param>
/// <param name="layer">The layer value to check for</param>
/// <returns>True if the layer is in the mask, false otherwise</returns>
public static bool ContainsBitwise(this LayerMask mask, int layer)
{
// Adjust for the -1 offset as specifically requested
int adjustedLayer = layer - 1;
return (mask.value & (1 << adjustedLayer)) != 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3e92a12c248d4b9ab06fcc0ba9c63ef3
timeCreated: 1758717247

View File

@@ -26,13 +26,11 @@ MonoBehaviour:
bubbleWobbleMinScale: 0.2 bubbleWobbleMinScale: 0.2
bubbleWobbleMaxScale: 1.2 bubbleWobbleMaxScale: 1.2
bubbleSurfacingSpeedFactor: 0.5 bubbleSurfacingSpeedFactor: 0.5
obstacleLayer: 9 obstacleLayer: 11
obstacleTileLayerMask:
serializedVersion: 2
m_Bits: 0
obstacleUseObjectPooling: 1 obstacleUseObjectPooling: 1
obstacleMaxPerPrefabPoolSize: 3 obstacleMaxPerPrefabPoolSize: 3
obstacleTotalMaxPoolSize: 15 obstacleTotalMaxPoolSize: 15
trenchTileLayer: 13
trenchTileUseObjectPooling: 1 trenchTileUseObjectPooling: 1
trenchTileMaxPerPrefabPoolSize: 2 trenchTileMaxPerPrefabPoolSize: 2
trenchTileTotalMaxPoolSize: 10 trenchTileTotalMaxPoolSize: 10
@@ -44,12 +42,12 @@ MonoBehaviour:
playerSpeedToAmplitude: 2 playerSpeedToAmplitude: 2
playerMaxRotationLimit: 45 playerMaxRotationLimit: 45
playerVerticalFrequency: 0.5 playerVerticalFrequency: 0.5
playerVerticalAmplitude: 0.5 playerVerticalAmplitude: 0.2
playerVelocitySmoothing: 10 playerVelocitySmoothing: 10
playerRotationSmoothing: 10 playerRotationSmoothing: 10
playerObstacleLayerMask: playerObstacleLayerMask:
serializedVersion: 2 serializedVersion: 2
m_Bits: 4294967295 m_Bits: 5120
blockInputDuringImmunity: 1 blockInputDuringImmunity: 1
bumpMode: 0 bumpMode: 0
bumpCurve: bumpCurve:

View File

@@ -12,8 +12,37 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0ce4dba7a1c54e73b1b3d7131a1c0570, type: 3} m_Script: {fileID: 11500000, guid: 0ce4dba7a1c54e73b1b3d7131a1c0570, type: 3}
m_Name: MinigameSettings m_Name: MinigameSettings
m_EditorClassIdentifier: m_EditorClassIdentifier:
endlessDescenderLerpSpeed: 2.03 lerpSpeed: 2
endlessDescenderMaxOffset: 10 maxOffset: 10
endlessDescenderClampXMin: -3.5 clampXMin: -3.5
endlessDescenderClampXMax: 3.5 clampXMax: 3.5
endlessDescenderSpeedExponent: 0.97 speedExponent: 0.97
tapMaxDistance: 0.5
tapDecelerationRate: 5
baseSpawnProbability: 0.2
maxSpawnProbability: 0.5
probabilityIncreaseRate: 0.01
guaranteedSpawnTime: 30
spawnCooldown: 5
basePoints: 100
depthMultiplier: 10
speedTransitionDuration: 2
surfacingSpeedFactor: 3
surfacingSpawnDelay: 5
initialTileCount: 3
tileSpawnBuffer: 1
moveSpeed: 2
speedUpFactor: 0
speedUpInterval: 10
maxMoveSpeed: 12
velocityCalculationInterval: 0.5
obstacleSpawnInterval: 2
obstacleSpawnIntervalVariation: 0.5
obstacleMaxSpawnAttempts: 10
obstacleSpawnCollisionRadius: 1
obstacleMinMoveSpeed: 1
obstacleMaxMoveSpeed: 4
damageImmunityDuration: 1
bumpForce: 5
smoothMoveSpeed: 8
blockInputDuringBump: 1