235 lines
8.4 KiB
C#
235 lines
8.4 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace Minigames.DivingForPictures
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// Collision behavior that bumps the player toward the center of the trench.
|
|||
|
|
/// Provides two modes: impulse (force-based push) or smooth movement to center.
|
|||
|
|
/// </summary>
|
|||
|
|
public class PlayerBumpCollisionBehavior : PlayerCollisionBehavior
|
|||
|
|
{
|
|||
|
|
[Header("Bump Settings")]
|
|||
|
|
[Tooltip("Type of bump response: Impulse pushes with force, SmoothToCenter moves directly to center")]
|
|||
|
|
[SerializeField] private BumpMode bumpMode = BumpMode.Impulse;
|
|||
|
|
|
|||
|
|
[Tooltip("Force strength for impulse bumps - higher values push further toward center")]
|
|||
|
|
[SerializeField] private float bumpForce = 5.0f;
|
|||
|
|
|
|||
|
|
[Tooltip("Speed for smooth movement to center (units per second)")]
|
|||
|
|
[SerializeField] private float smoothMoveSpeed = 8.0f;
|
|||
|
|
|
|||
|
|
[Tooltip("Animation curve controlling bump movement over time")]
|
|||
|
|
[SerializeField] private AnimationCurve bumpCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 2f), new Keyframe(1f, 1f, 0f, 0f));
|
|||
|
|
|
|||
|
|
[Tooltip("Whether to block player input during bump movement")]
|
|||
|
|
[SerializeField] private bool blockInputDuringBump = true;
|
|||
|
|
|
|||
|
|
public enum BumpMode
|
|||
|
|
{
|
|||
|
|
Impulse, // Force-based push toward center (distance depends on force)
|
|||
|
|
SmoothToCenter // Smooth movement to center with configurable speed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool _isBumping;
|
|||
|
|
private float _bumpTimer;
|
|||
|
|
private float _bumpStartX;
|
|||
|
|
private float _bumpTargetX;
|
|||
|
|
private float _bumpDuration;
|
|||
|
|
private bool _bumpInputBlocked; // Tracks bump-specific input blocking
|
|||
|
|
|
|||
|
|
protected override void Update()
|
|||
|
|
{
|
|||
|
|
base.Update();
|
|||
|
|
|
|||
|
|
// Handle bump movement
|
|||
|
|
if (_isBumping)
|
|||
|
|
{
|
|||
|
|
_bumpTimer -= Time.deltaTime;
|
|||
|
|
|
|||
|
|
if (_bumpTimer <= 0f)
|
|||
|
|
{
|
|||
|
|
// Bump finished
|
|||
|
|
_isBumping = false;
|
|||
|
|
if (_bumpInputBlocked)
|
|||
|
|
{
|
|||
|
|
RestoreBumpInput();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ensure we end exactly at target
|
|||
|
|
if (playerCharacter != null)
|
|||
|
|
{
|
|||
|
|
Vector3 currentPos = playerCharacter.transform.position;
|
|||
|
|
playerCharacter.transform.position = new Vector3(_bumpTargetX, currentPos.y, currentPos.z);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// Apply bump movement
|
|||
|
|
float progress = 1f - (_bumpTimer / _bumpDuration);
|
|||
|
|
float curveValue = bumpCurve.Evaluate(progress);
|
|||
|
|
|
|||
|
|
float currentX = Mathf.Lerp(_bumpStartX, _bumpTargetX, curveValue);
|
|||
|
|
|
|||
|
|
// Apply the position to the player character
|
|||
|
|
if (playerCharacter != null)
|
|||
|
|
{
|
|||
|
|
Vector3 currentPos = playerCharacter.transform.position;
|
|||
|
|
playerCharacter.transform.position = new Vector3(currentX, currentPos.y, currentPos.z);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void HandleCollisionResponse(Collider2D obstacle)
|
|||
|
|
{
|
|||
|
|
switch (bumpMode)
|
|||
|
|
{
|
|||
|
|
case BumpMode.Impulse:
|
|||
|
|
StartImpulseBump();
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case BumpMode.SmoothToCenter:
|
|||
|
|
StartSmoothMoveToCenter();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.Log($"[PlayerBumpCollisionBehavior] Collision handled with {bumpMode} mode");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Starts an impulse bump toward the center with force-based distance
|
|||
|
|
/// </summary>
|
|||
|
|
private void StartImpulseBump()
|
|||
|
|
{
|
|||
|
|
if (playerCharacter == null) return;
|
|||
|
|
|
|||
|
|
float currentX = playerCharacter.transform.position.x;
|
|||
|
|
|
|||
|
|
// Calculate bump distance based on force and current position
|
|||
|
|
float directionToCenter = currentX > 0 ? -1f : 1f; // Direction toward center
|
|||
|
|
|
|||
|
|
// Calculate target position - closer to center based on bump force
|
|||
|
|
float bumpDistance = 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))
|
|||
|
|
{
|
|||
|
|
targetX = 0f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Set bump parameters
|
|||
|
|
_bumpStartX = currentX;
|
|||
|
|
_bumpTargetX = targetX;
|
|||
|
|
_bumpDuration = 0.5f; // Fixed duration for impulse
|
|||
|
|
|
|||
|
|
StartBump();
|
|||
|
|
|
|||
|
|
Debug.Log($"[PlayerBumpCollisionBehavior] Starting impulse bump from X={_bumpStartX} to X={_bumpTargetX} (force={bumpForce})");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Starts smooth movement to the center
|
|||
|
|
/// </summary>
|
|||
|
|
private void StartSmoothMoveToCenter()
|
|||
|
|
{
|
|||
|
|
if (playerCharacter == null) return;
|
|||
|
|
|
|||
|
|
float currentX = playerCharacter.transform.position.x;
|
|||
|
|
float distanceToCenter = Mathf.Abs(currentX);
|
|||
|
|
|
|||
|
|
// Set bump parameters
|
|||
|
|
_bumpStartX = currentX;
|
|||
|
|
_bumpTargetX = 0f; // Always move to center
|
|||
|
|
_bumpDuration = distanceToCenter / smoothMoveSpeed; // Duration based on distance and speed
|
|||
|
|
|
|||
|
|
StartBump();
|
|||
|
|
|
|||
|
|
Debug.Log($"[PlayerBumpCollisionBehavior] Starting smooth move to center from X={_bumpStartX} (speed={smoothMoveSpeed}, duration={_bumpDuration:F2}s)");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Common bump initialization
|
|||
|
|
/// </summary>
|
|||
|
|
private void StartBump()
|
|||
|
|
{
|
|||
|
|
_isBumping = true;
|
|||
|
|
_bumpTimer = _bumpDuration;
|
|||
|
|
|
|||
|
|
// Block player input if enabled (use bump-specific blocking)
|
|||
|
|
if (blockInputDuringBump && playerController != null && playerController.enabled)
|
|||
|
|
{
|
|||
|
|
playerController.enabled = false;
|
|||
|
|
_bumpInputBlocked = true;
|
|||
|
|
Debug.Log("[PlayerBumpCollisionBehavior] Player input blocked during bump");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Restores player input after bump movement
|
|||
|
|
/// </summary>
|
|||
|
|
private void RestoreBumpInput()
|
|||
|
|
{
|
|||
|
|
if (_bumpInputBlocked && playerController != null)
|
|||
|
|
{
|
|||
|
|
playerController.enabled = true;
|
|||
|
|
_bumpInputBlocked = false;
|
|||
|
|
|
|||
|
|
// Update the controller's target position to current position to prevent snapping
|
|||
|
|
UpdateControllerTarget();
|
|||
|
|
|
|||
|
|
Debug.Log("[PlayerBumpCollisionBehavior] Player input restored after bump");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void OnImmunityEnd()
|
|||
|
|
{
|
|||
|
|
base.OnImmunityEnd();
|
|||
|
|
|
|||
|
|
// Stop any ongoing bump if immunity ends
|
|||
|
|
if (_isBumping)
|
|||
|
|
{
|
|||
|
|
_isBumping = false;
|
|||
|
|
if (_bumpInputBlocked)
|
|||
|
|
{
|
|||
|
|
RestoreBumpInput();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Public method to change bump mode at runtime
|
|||
|
|
/// </summary>
|
|||
|
|
public void SetBumpMode(BumpMode mode)
|
|||
|
|
{
|
|||
|
|
bumpMode = mode;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Public method to change bump force at runtime
|
|||
|
|
/// </summary>
|
|||
|
|
public void SetBumpForce(float force)
|
|||
|
|
{
|
|||
|
|
bumpForce = force;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Public method to change smooth move speed at runtime
|
|||
|
|
/// </summary>
|
|||
|
|
public void SetSmoothMoveSpeed(float speed)
|
|||
|
|
{
|
|||
|
|
smoothMoveSpeed = speed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Check if player is currently being bumped
|
|||
|
|
/// </summary>
|
|||
|
|
public bool IsBumping => _isBumping;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Check if input is currently blocked by bump
|
|||
|
|
/// </summary>
|
|||
|
|
public bool IsBumpInputBlocked => _bumpInputBlocked;
|
|||
|
|
}
|
|||
|
|
}
|