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