112 lines
4.0 KiB
C#
Raw Permalink 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.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);
}
}