112 lines
4.0 KiB
C#
112 lines
4.0 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
|
||
public class RealisticSinking : MonoBehaviour
|
||
{
|
||
[Header("Sinking Parameters")]
|
||
public float sinkDuration = 20f;
|
||
public float maxRollAngle = 45f;
|
||
public float maxPitchAngle = 20f;
|
||
public float maxSinkDepth = 300f;
|
||
|
||
[Header("Inertia Parameters")]
|
||
public float driftDeceleration = 0.5f; // Насколько быстро теряет скорость (0 = не теряет, 1 = мгновенно)
|
||
|
||
[Header("Effects")]
|
||
public GameObject finalExplosionPrefab;
|
||
public ParticleSystem bubblesEffect;
|
||
|
||
private Vector3 originalPosition;
|
||
private Quaternion originalRotation;
|
||
private float hitSide = 1f;
|
||
private float pitchDirection = 1f;
|
||
private bool isSinking = false;
|
||
|
||
// Для инерции
|
||
private Vector3 initialVelocity;
|
||
private Vector3 driftDirection;
|
||
private float currentSpeed;
|
||
private bool hasInertia = false;
|
||
|
||
public void OnTorpedoHit(Vector3 hitPoint, Vector3 currentVelocity)
|
||
{
|
||
if (isSinking) return;
|
||
isSinking = true;
|
||
|
||
originalPosition = transform.position;
|
||
originalRotation = transform.rotation;
|
||
|
||
// Сохраняем скорость и направление движения
|
||
initialVelocity = currentVelocity;
|
||
currentSpeed = currentVelocity.magnitude;
|
||
driftDirection = currentVelocity.normalized;
|
||
hasInertia = currentSpeed > 0.1f;
|
||
|
||
// Определяем борт и место попадания
|
||
Vector3 localHit = transform.InverseTransformPoint(hitPoint);
|
||
hitSide = Mathf.Sign(localHit.x);
|
||
|
||
// Дифферент зависит от попадания по длине корабля
|
||
float normalizedZ = Mathf.Clamp(localHit.z / 5f, -1f, 1f);
|
||
pitchDirection = -normalizedZ;
|
||
|
||
StartCoroutine(SinkAndRoll());
|
||
}
|
||
|
||
IEnumerator SinkAndRoll()
|
||
{
|
||
float elapsed = 0;
|
||
|
||
while (elapsed < sinkDuration)
|
||
{
|
||
elapsed += Time.deltaTime;
|
||
float t = elapsed / sinkDuration;
|
||
|
||
// 1. Управляем инерцией (плавное замедление)
|
||
if (hasInertia)
|
||
{
|
||
// Скорость падает со временем (чем сильнее повреждён, тем быстрее)
|
||
float deceleration = Mathf.Lerp(0.1f, driftDeceleration, t);
|
||
currentSpeed = Mathf.Max(0, currentSpeed - deceleration * Time.deltaTime);
|
||
|
||
// Дрейфуем с текущей скоростью
|
||
if (currentSpeed > 0.1f)
|
||
{
|
||
transform.position += driftDirection * currentSpeed * Time.deltaTime;
|
||
// Корректируем originalPosition, чтобы оседание продолжалось от новой позиции
|
||
originalPosition = transform.position;
|
||
}
|
||
else
|
||
{
|
||
hasInertia = false;
|
||
}
|
||
}
|
||
|
||
// 2. Крен и дифферент
|
||
float rollCurve = Mathf.Sin(t * Mathf.PI * 0.7f);
|
||
float sinkCurve = t * t;
|
||
|
||
float currentRoll = maxRollAngle * hitSide * rollCurve;
|
||
float currentPitch = maxPitchAngle * pitchDirection * t;
|
||
|
||
transform.rotation = originalRotation * Quaternion.Euler(currentPitch, 0, currentRoll);
|
||
|
||
// 3. Оседание
|
||
float sinkOffset = Mathf.Lerp(0, maxSinkDepth, sinkCurve);
|
||
transform.position = originalPosition - transform.up * sinkOffset;
|
||
|
||
// 4. Эффекты
|
||
if (t > 0.7f && bubblesEffect != null && !bubblesEffect.isPlaying)
|
||
bubblesEffect.Play();
|
||
|
||
yield return null;
|
||
}
|
||
|
||
// Финальный взрыв
|
||
if (finalExplosionPrefab != null)
|
||
Instantiate(finalExplosionPrefab, transform.position, Quaternion.identity);
|
||
|
||
yield return new WaitForSeconds(0.3f);
|
||
Destroy(gameObject);
|
||
}
|
||
} |