sea-battle-vr/Assets/Scripts/Gameplay/PlayerDiveSystem.cs
sega 7189b03509 Проработка сыстемы ныряния
- стекающая вода при всплытии
-пузыри под водой
-кулдаун на погружение
2026-05-15 14:06:38 +03:00

153 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}