153 lines
4.9 KiB
C#
153 lines
4.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
public class PlayerDiveSystem : MonoBehaviour
|
||
{
|
||
public event Action Surfaced;
|
||
|
||
[Header("Настройки погружения")]
|
||
[SerializeField] private Transform UpPoint;
|
||
[SerializeField] private Transform DownPoint;
|
||
[SerializeField] private float MaxSpeed = 5f;
|
||
[SerializeField] private float SmoothTime = 0.5f; // Время разгона/торможения
|
||
[SerializeField] private float SurfacedCooldown = 2f; // Cooldown на событие Surfaced
|
||
private float currentHeightVelocity = 0f;
|
||
private float totalHeight;
|
||
|
||
[Header("Давление")]
|
||
[SerializeField] private float DepthPercentToStartPressure = 0.4f;
|
||
[SerializeField] private float PressureMultiplier = 0.2f;
|
||
[SerializeField, Range(0,1)] private float PressurePercentToResetCooldown = 0.7f;
|
||
|
||
[Header("Пузыри")]
|
||
[SerializeField] List<ParticleSystem> bubbleParticles;
|
||
|
||
private bool forceMoveUp = false;
|
||
private float lastSurfacedTime = -Mathf.Infinity; // Время последнего вызова Surfaced
|
||
private bool wasUnderPressure = false;
|
||
private bool wasMovingUp = false;
|
||
|
||
public float PressurePercent { get; private set; }
|
||
public float DepthPercent => (UpPoint.position.y - transform.position.y) / totalHeight;
|
||
public bool Dive { private get; set; }
|
||
|
||
|
||
private void Awake()
|
||
{
|
||
totalHeight = UpPoint.position.y - DownPoint.position.y;
|
||
foreach (var particle in bubbleParticles) particle.Stop();
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
|
||
|
||
bool isMovingUp = !Dive && !forceMoveUp || forceMoveUp;
|
||
bool isUnderPressure = DepthPercent > DepthPercentToStartPressure;
|
||
|
||
ProcessPressure();
|
||
CheckAndTriggerSurfaced(isMovingUp, isUnderPressure);
|
||
|
||
if (forceMoveUp)
|
||
{
|
||
MoveToHeight(UpPoint.position.y);
|
||
// Достигли верха? Тогда выходим
|
||
if (PressurePercent < PressurePercentToResetCooldown)
|
||
{
|
||
forceMoveUp = false;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (PressurePercent >= 1f)
|
||
{
|
||
forceMoveUp = true;
|
||
return;
|
||
}
|
||
|
||
var targetHeight = Dive ? DownPoint.position.y : UpPoint.position.y;
|
||
MoveToHeight(targetHeight);
|
||
|
||
wasUnderPressure = isUnderPressure;
|
||
wasMovingUp = isMovingUp;
|
||
|
||
}
|
||
|
||
private void CheckAndTriggerSurfaced(bool isMovingUp, bool isUnderPressure)
|
||
{
|
||
// Проверяем: движемся вверх, пересекаем границу давления, и прошло достаточно времени с последнего вызова
|
||
bool crossingPressureBoundary = !isUnderPressure && wasUnderPressure;
|
||
bool canTrigger = Time.time - lastSurfacedTime >= SurfacedCooldown;
|
||
|
||
if (isMovingUp && crossingPressureBoundary && canTrigger)
|
||
{
|
||
TriggerSurfaced();
|
||
}
|
||
}
|
||
|
||
private void TriggerSurfaced()
|
||
{
|
||
Surfaced?.Invoke();
|
||
lastSurfacedTime = Time.time;
|
||
Debug.Log($"Surfaced triggered! Time: {lastSurfacedTime}");
|
||
}
|
||
|
||
private void ProcessPressure()
|
||
{
|
||
if (DepthPercent > DepthPercentToStartPressure)
|
||
{
|
||
AddPressure();
|
||
foreach(var bubble in bubbleParticles)
|
||
{
|
||
if(!bubble.isPlaying) bubble.Play();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ReducePressure();
|
||
}
|
||
|
||
void AddPressure()
|
||
{
|
||
float pressureStrength = DepthPercent * PressureMultiplier;
|
||
PressurePercent += pressureStrength * Time.deltaTime;
|
||
PressurePercent = Mathf.Clamp01(PressurePercent);
|
||
}
|
||
|
||
void ReducePressure()
|
||
{
|
||
PressurePercent -= PressureMultiplier * Time.deltaTime;
|
||
PressurePercent = Mathf.Clamp01(PressurePercent);
|
||
|
||
foreach (var bubble in bubbleParticles)
|
||
{
|
||
if (bubble.isPlaying) bubble.Stop();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void MoveToHeight(float targetHeight)
|
||
{
|
||
float currentY = transform.position.y;
|
||
float newY = Mathf.SmoothDamp(
|
||
currentY,
|
||
targetHeight,
|
||
ref currentHeightVelocity,
|
||
SmoothTime,
|
||
MaxSpeed
|
||
);
|
||
|
||
Vector3 newPosition = transform.position;
|
||
newPosition.y = newY;
|
||
transform.position = newPosition;
|
||
|
||
float magnitude = UpPoint.position.y - DownPoint.position.y;
|
||
float t = (transform.position.y - DownPoint.position.y) / magnitude;
|
||
|
||
float minDensity = 0.0001f; // Минимальная плотность (на поверхности)
|
||
float maxDensity = 0.01f; // Максимальная плотность (на дне)
|
||
RenderSettings.fogDensity = Mathf.Lerp(maxDensity, minDensity, t);
|
||
}
|
||
}
|