The feel is fine
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
Assets/Scripts/Utilities.meta
Normal file
3
Assets/Scripts/Utilities.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d54ca063d685467f9cb2c05507ac833f
|
||||||
|
timeCreated: 1758717247
|
||||||
55
Assets/Scripts/Utilities/UnityExtensions.cs
Normal file
55
Assets/Scripts/Utilities/UnityExtensions.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Scripts/Utilities/UnityExtensions.cs.meta
Normal file
3
Assets/Scripts/Utilities/UnityExtensions.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3e92a12c248d4b9ab06fcc0ba9c63ef3
|
||||||
|
timeCreated: 1758717247
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user