Improvements and touchups to a more event-driven flow and fake physics
This commit is contained in:
@@ -4,8 +4,9 @@ using Pooling;
|
|||||||
namespace Minigames.DivingForPictures
|
namespace Minigames.DivingForPictures
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Complete floating obstacle component that handles data, movement, and pooling.
|
/// Complete floating obstacle component that handles movement and pooling.
|
||||||
/// Obstacles move upward toward the surface. Collision detection is now handled by the player.
|
/// Obstacles move upward toward the surface. Collision detection is handled by the player.
|
||||||
|
/// Once an obstacle hits the player, its collider is disabled to prevent further collisions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FloatingObstacle : MonoBehaviour, IPoolable
|
public class FloatingObstacle : MonoBehaviour, IPoolable
|
||||||
{
|
{
|
||||||
@@ -13,9 +14,6 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("Index of the prefab this obstacle was created from")]
|
[Tooltip("Index of the prefab this obstacle was created from")]
|
||||||
[SerializeField] private int prefabIndex;
|
[SerializeField] private int prefabIndex;
|
||||||
|
|
||||||
[Tooltip("Damage this obstacle deals to the player")]
|
|
||||||
[SerializeField] private float damage = 1f;
|
|
||||||
|
|
||||||
[Tooltip("Movement speed of this obstacle")]
|
[Tooltip("Movement speed of this obstacle")]
|
||||||
[SerializeField] private float moveSpeed = 2f;
|
[SerializeField] private float moveSpeed = 2f;
|
||||||
|
|
||||||
@@ -34,23 +32,14 @@ namespace Minigames.DivingForPictures
|
|||||||
set => prefabIndex = value;
|
set => prefabIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Damage
|
|
||||||
{
|
|
||||||
get => damage;
|
|
||||||
set => damage = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MoveSpeed
|
public float MoveSpeed
|
||||||
{
|
{
|
||||||
get => moveSpeed;
|
get => moveSpeed;
|
||||||
set => moveSpeed = value;
|
set => moveSpeed = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasDealtDamage => _hasDealtDamage;
|
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
private Collider2D _collider;
|
private Collider2D _collider;
|
||||||
private bool _hasDealtDamage;
|
|
||||||
private Camera _mainCamera;
|
private Camera _mainCamera;
|
||||||
private float _screenTop;
|
private float _screenTop;
|
||||||
|
|
||||||
@@ -90,14 +79,15 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks this obstacle as having dealt damage (called by PlayerDamageCollisionBehavior)
|
/// Disables the collider after hitting the player to prevent further collisions
|
||||||
|
/// This is more performant than tracking hit state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void MarkDamageDealt()
|
public void MarkDamageDealt()
|
||||||
{
|
{
|
||||||
if (!_hasDealtDamage)
|
if (_collider != null && _collider.enabled)
|
||||||
{
|
{
|
||||||
_hasDealtDamage = true;
|
_collider.enabled = false;
|
||||||
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} dealt {damage} damage to player");
|
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} hit player - collider disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,9 +142,14 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnSpawn()
|
public void OnSpawn()
|
||||||
{
|
{
|
||||||
_hasDealtDamage = false;
|
|
||||||
_screenTop = 0f; // Reset cached screen bounds
|
_screenTop = 0f; // Reset cached screen bounds
|
||||||
|
|
||||||
|
// Re-enable the collider for reuse
|
||||||
|
if (_collider != null)
|
||||||
|
{
|
||||||
|
_collider.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the obstacle is active and visible
|
// Ensure the obstacle is active and visible
|
||||||
gameObject.SetActive(true);
|
gameObject.SetActive(true);
|
||||||
|
|
||||||
@@ -166,7 +161,11 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnDespawn()
|
public void OnDespawn()
|
||||||
{
|
{
|
||||||
_hasDealtDamage = false;
|
// Re-enable collider for next use (in case it was disabled)
|
||||||
|
if (_collider != null)
|
||||||
|
{
|
||||||
|
_collider.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} despawned");
|
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} despawned");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,49 +8,16 @@ namespace Minigames.DivingForPictures
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ObstacleCollision : PlayerCollisionBehavior
|
public class ObstacleCollision : PlayerCollisionBehavior
|
||||||
{
|
{
|
||||||
[Header("Damage Settings")]
|
|
||||||
[Tooltip("Base damage amount dealt by obstacles")]
|
|
||||||
[SerializeField] private float baseDamage = 1f;
|
|
||||||
|
|
||||||
[Tooltip("Whether to use the obstacle's individual damage value or the base damage")]
|
|
||||||
[SerializeField] private bool useObstacleDamageValue = true;
|
|
||||||
|
|
||||||
protected override void HandleCollisionResponse(Collider2D obstacle)
|
protected override void HandleCollisionResponse(Collider2D obstacle)
|
||||||
{
|
{
|
||||||
float damageAmount = baseDamage;
|
// Mark the obstacle as having dealt damage to prevent multiple hits
|
||||||
|
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||||
// Try to get damage from the obstacle component if enabled
|
if (obstacleComponent != null)
|
||||||
if (useObstacleDamageValue)
|
|
||||||
{
|
{
|
||||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
obstacleComponent.MarkDamageDealt();
|
||||||
if (obstacleComponent != null)
|
|
||||||
{
|
|
||||||
damageAmount = obstacleComponent.Damage;
|
|
||||||
|
|
||||||
// Mark the obstacle as having dealt damage to prevent multiple hits
|
|
||||||
obstacleComponent.MarkDamageDealt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply damage (this could be extended to integrate with a health system)
|
Debug.Log($"[ObstacleCollision] Player hit by obstacle {obstacle.gameObject.name}");
|
||||||
ApplyDamage(damageAmount);
|
|
||||||
|
|
||||||
Debug.Log($"[ObstacleCollision] Player took {damageAmount} damage from obstacle {obstacle.gameObject.name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies damage to the player
|
|
||||||
/// Override this method to integrate with your health/damage system
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="damage">Amount of damage to apply</param>
|
|
||||||
protected virtual void ApplyDamage(float damage)
|
|
||||||
{
|
|
||||||
// For now, just log the damage
|
|
||||||
// In a full implementation, this would reduce player health, trigger UI updates, etc.
|
|
||||||
Debug.Log($"[ObstacleCollision] Applied {damage} damage to player");
|
|
||||||
|
|
||||||
// TODO: Integrate with health system when available
|
|
||||||
// Example: playerHealth.TakeDamage(damage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -73,21 +40,5 @@ namespace Minigames.DivingForPictures
|
|||||||
Debug.Log($"[ObstacleCollision] Damage immunity ended");
|
Debug.Log($"[ObstacleCollision] Damage immunity ended");
|
||||||
// No special handling needed - shared immunity system handles collider re-enabling
|
// No special handling needed - shared immunity system handles collider re-enabling
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public method to set base damage at runtime
|
|
||||||
/// </summary>
|
|
||||||
public void SetBaseDamage(float damage)
|
|
||||||
{
|
|
||||||
baseDamage = damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public method to toggle between base damage and obstacle-specific damage
|
|
||||||
/// </summary>
|
|
||||||
public void SetUseObstacleDamage(bool useObstacleDamage)
|
|
||||||
{
|
|
||||||
useObstacleDamageValue = useObstacleDamage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,6 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
[Tooltip("Maximum movement speed for spawned obstacles")]
|
[Tooltip("Maximum movement speed for spawned obstacles")]
|
||||||
[SerializeField] private float maxMoveSpeed = 4f;
|
[SerializeField] private float maxMoveSpeed = 4f;
|
||||||
|
|
||||||
[Tooltip("Minimum damage dealt by obstacles")]
|
|
||||||
[SerializeField] private float minDamage = 0.5f;
|
|
||||||
|
|
||||||
[Tooltip("Maximum damage dealt by obstacles")]
|
|
||||||
[SerializeField] private float maxDamage = 2f;
|
|
||||||
|
|
||||||
[Header("Object Pooling")]
|
[Header("Object Pooling")]
|
||||||
[Tooltip("Whether to use object pooling for obstacles")]
|
[Tooltip("Whether to use object pooling for obstacles")]
|
||||||
@@ -356,7 +350,6 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
// Randomize properties
|
// Randomize properties
|
||||||
obstacleComponent.MoveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed);
|
obstacleComponent.MoveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed);
|
||||||
obstacleComponent.Damage = Random.Range(minDamage, maxDamage);
|
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -423,15 +416,6 @@ namespace Minigames.DivingForPictures
|
|||||||
maxMoveSpeed = max;
|
maxMoveSpeed = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public method to set damage range at runtime
|
|
||||||
/// </summary>
|
|
||||||
public void SetDamageRange(float min, float max)
|
|
||||||
{
|
|
||||||
minDamage = min;
|
|
||||||
maxDamage = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the count of currently active obstacles
|
/// Gets the count of currently active obstacles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -60,16 +60,16 @@ namespace Minigames.DivingForPictures
|
|||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
// Subscribe to damage events
|
// Subscribe to immunity events (renamed from damage events)
|
||||||
PlayerCollisionBehavior.OnDamageStart += StartBlinking;
|
PlayerCollisionBehavior.OnImmunityStarted += StartBlinking;
|
||||||
PlayerCollisionBehavior.OnDamageEnd += StopBlinking;
|
PlayerCollisionBehavior.OnImmunityEnded += StopBlinking;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDisable()
|
private void OnDisable()
|
||||||
{
|
{
|
||||||
// Unsubscribe from damage events
|
// Unsubscribe from immunity events
|
||||||
PlayerCollisionBehavior.OnDamageStart -= StartBlinking;
|
PlayerCollisionBehavior.OnImmunityStarted -= StartBlinking;
|
||||||
PlayerCollisionBehavior.OnDamageEnd -= StopBlinking;
|
PlayerCollisionBehavior.OnImmunityEnded -= StopBlinking;
|
||||||
|
|
||||||
// Stop any ongoing blink effect
|
// Stop any ongoing blink effect
|
||||||
if (_blinkCoroutine != null)
|
if (_blinkCoroutine != null)
|
||||||
|
|||||||
@@ -34,28 +34,37 @@ namespace Minigames.DivingForPictures
|
|||||||
private static MonoBehaviour _coroutineRunner;
|
private static MonoBehaviour _coroutineRunner;
|
||||||
private static Collider2D _sharedPlayerCollider;
|
private static Collider2D _sharedPlayerCollider;
|
||||||
|
|
||||||
// Events for damage state changes
|
// Events for immunity and damage state changes
|
||||||
public static event Action OnDamageStart;
|
public static event Action OnImmunityStarted;
|
||||||
public static event Action OnDamageEnd;
|
public static event Action OnImmunityEnded;
|
||||||
|
public static event Action OnDamageTaken;
|
||||||
|
|
||||||
// Instance tracking for shared state management
|
// Instance tracking for shared state management
|
||||||
private static readonly System.Collections.Generic.HashSet<PlayerCollisionBehavior> _allInstances =
|
private static readonly System.Collections.Generic.HashSet<PlayerCollisionBehavior> _allInstances =
|
||||||
new System.Collections.Generic.HashSet<PlayerCollisionBehavior>();
|
new System.Collections.Generic.HashSet<PlayerCollisionBehavior>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Public static method to trigger damage start event from external classes
|
/// Public static method to trigger immunity start event from external classes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void TriggerDamageStart()
|
public static void TriggerImmunityStarted()
|
||||||
{
|
{
|
||||||
OnDamageStart?.Invoke();
|
OnImmunityStarted?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Public static method to trigger damage end event from external classes
|
/// Public static method to trigger immunity end event from external classes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void TriggerDamageEnd()
|
public static void TriggerImmunityEnded()
|
||||||
{
|
{
|
||||||
OnDamageEnd?.Invoke();
|
OnImmunityEnded?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public static method to trigger damage taken event from external classes
|
||||||
|
/// </summary>
|
||||||
|
public static void TriggerDamageTaken()
|
||||||
|
{
|
||||||
|
OnDamageTaken?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool wasInputBlocked;
|
protected bool wasInputBlocked;
|
||||||
@@ -148,6 +157,9 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
if (_isGloballyImmune) return;
|
if (_isGloballyImmune) return;
|
||||||
|
|
||||||
|
// Trigger damage taken event first
|
||||||
|
OnDamageTaken?.Invoke();
|
||||||
|
|
||||||
// Start shared immunity period
|
// Start shared immunity period
|
||||||
StartGlobalImmunity();
|
StartGlobalImmunity();
|
||||||
|
|
||||||
@@ -191,8 +203,8 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast damage start event
|
// Broadcast immunity start event
|
||||||
OnDamageStart?.Invoke();
|
OnImmunityStarted?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -225,8 +237,8 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast damage end event
|
// Broadcast immunity end event
|
||||||
OnDamageEnd?.Invoke();
|
OnImmunityEnded?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -352,7 +364,7 @@ namespace Minigames.DivingForPictures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnDamageEnd?.Invoke();
|
OnImmunityEnded?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user