165 lines
5.8 KiB
C#
165 lines
5.8 KiB
C#
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
|
||
public class EchoTrigger : MonoBehaviour
|
||
{
|
||
[Header("Связь с шейдером")]
|
||
public Material echoMaterial;
|
||
|
||
[Header("Настройки шагов")]
|
||
public float stepDistance = 1.5f;
|
||
public float waveSpeed = 15f;
|
||
|
||
[Header("Радиусы звука (Шум)")]
|
||
public float sneakRadius = 5f;
|
||
public float walkRadius = 15f;
|
||
public float runRadius = 30f;
|
||
|
||
[Header("Яркость волны (Интенсивность)")]
|
||
public float sneakIntensity = 0.3f; // Тусклый свет для стелса
|
||
public float walkIntensity = 1.0f; // Обычный свет для шага
|
||
public float runIntensity = 3.0f; // Очень яркая вспышка для бега
|
||
|
||
// Пул из 3 одновременных волн
|
||
private const int MAX_WAVES = 3;
|
||
private float[] waveRadii = new float[MAX_WAVES];
|
||
private float[] waveMaxRadii = new float[MAX_WAVES];
|
||
private float[] waveIntensities = new float[MAX_WAVES]; // Память для яркости каждой волны
|
||
private bool[] waveActive = new bool[MAX_WAVES];
|
||
|
||
public static EchoTrigger Instance;
|
||
|
||
private Vector3 lastPosition;
|
||
private float distanceMoved = 0f;
|
||
|
||
void Awake()
|
||
{
|
||
if (Instance == null) Instance = this;
|
||
}
|
||
|
||
void Start()
|
||
{
|
||
if (echoMaterial != null)
|
||
{
|
||
for (int i = 0; i < MAX_WAVES; i++)
|
||
{
|
||
echoMaterial.SetFloat("_EchoRadius" + (i + 1), 0f);
|
||
echoMaterial.SetFloat("_EchoOpacity" + (i + 1), 0f);
|
||
}
|
||
}
|
||
lastPosition = transform.position;
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
if (echoMaterial == null) return;
|
||
|
||
Vector3 currentPos = new Vector3(transform.position.x, 0, transform.position.z);
|
||
Vector3 lastPos = new Vector3(lastPosition.x, 0, lastPosition.z);
|
||
|
||
distanceMoved += Vector3.Distance(currentPos, lastPos);
|
||
lastPosition = transform.position;
|
||
|
||
if (distanceMoved >= stepDistance)
|
||
{
|
||
distanceMoved = 0f;
|
||
TriggerStepWave();
|
||
}
|
||
|
||
for (int i = 0; i < MAX_WAVES; i++)
|
||
{
|
||
if (waveActive[i])
|
||
{
|
||
waveRadii[i] += waveSpeed * Time.deltaTime;
|
||
float currentRadius = waveRadii[i];
|
||
float maxRadius = waveMaxRadii[i];
|
||
float progress = Mathf.Clamp01(currentRadius / maxRadius);
|
||
|
||
// Плавное появление (Fade-in): в первые 18% пути волна мягко разгорается (без резкой вспышки)
|
||
float fadeIn = Mathf.SmoothStep(0f, 1f, progress / 0.18f);
|
||
// Плавное рассеивание (Fade-out): к концу облако плавно растворяется в темноте
|
||
float fadeOut = Mathf.Pow(1f - progress, 1.4f);
|
||
|
||
float opacity = (fadeIn * fadeOut) * waveIntensities[i];
|
||
opacity = Mathf.Max(0f, opacity);
|
||
|
||
echoMaterial.SetFloat("_EchoRadius" + (i + 1), currentRadius);
|
||
echoMaterial.SetFloat("_EchoOpacity" + (i + 1), opacity);
|
||
|
||
Shader.SetGlobalFloat("_EchoRadius" + (i + 1), currentRadius);
|
||
Shader.SetGlobalFloat("_EchoOpacity" + (i + 1), opacity);
|
||
|
||
if (currentRadius >= maxRadius)
|
||
{
|
||
waveActive[i] = false;
|
||
echoMaterial.SetFloat("_EchoRadius" + (i + 1), 0f);
|
||
echoMaterial.SetFloat("_EchoOpacity" + (i + 1), 0f);
|
||
Shader.SetGlobalFloat("_EchoRadius" + (i + 1), 0f);
|
||
Shader.SetGlobalFloat("_EchoOpacity" + (i + 1), 0f);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void TriggerStepWave()
|
||
{
|
||
var keyboard = Keyboard.current;
|
||
if (keyboard == null) return;
|
||
|
||
float targetMax = walkRadius;
|
||
float targetIntensity = walkIntensity;
|
||
|
||
if (keyboard.leftShiftKey.isPressed)
|
||
{
|
||
targetMax = runRadius;
|
||
targetIntensity = runIntensity;
|
||
}
|
||
else if (keyboard.leftCtrlKey.isPressed)
|
||
{
|
||
targetMax = sneakRadius;
|
||
targetIntensity = sneakIntensity;
|
||
}
|
||
|
||
TriggerExternalWave(transform.position, targetMax, targetIntensity);
|
||
}
|
||
|
||
public void TriggerExternalWave(Vector3 position, float targetMax, float targetIntensity)
|
||
{
|
||
// Ищем свободный слот
|
||
int waveIndex = -1;
|
||
for (int i = 0; i < MAX_WAVES; i++)
|
||
{
|
||
if (!waveActive[i])
|
||
{
|
||
waveIndex = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Если занято, берем самую старую волну
|
||
if (waveIndex == -1)
|
||
{
|
||
float maxRad = -1f;
|
||
for (int i = 0; i < MAX_WAVES; i++)
|
||
{
|
||
if (waveRadii[i] > maxRad)
|
||
{
|
||
maxRad = waveRadii[i];
|
||
waveIndex = i;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Назначаем волне её радиус и её личную яркость!
|
||
waveMaxRadii[waveIndex] = targetMax;
|
||
waveIntensities[waveIndex] = targetIntensity;
|
||
waveRadii[waveIndex] = 0f;
|
||
waveActive[waveIndex] = true;
|
||
|
||
// Начинаем плавно с 0, чтобы разгореться через fadeIn
|
||
echoMaterial.SetFloat("_EchoOpacity" + (waveIndex + 1), 0f);
|
||
echoMaterial.SetVector("_EchoPosition" + (waveIndex + 1), position);
|
||
Shader.SetGlobalFloat("_EchoOpacity" + (waveIndex + 1), 0f);
|
||
Shader.SetGlobalVector("_EchoPosition" + (waveIndex + 1), position);
|
||
}
|
||
} |