Danro/Assets/Scripts/Entities/LightActionsController.cs

144 lines
5.4 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 UnityEngine;
using UnityEngine.Rendering.Universal;
namespace RR.Common.Entities
{
public class LightActionsController : MonoBehaviour
{
private enum Mode { Blink, Pulse, Noise, Curve }
[Header("Target")]
[SerializeField] private Light[] lights3D;
[SerializeField] private Light2D[] lights2D;
[Tooltip("Доп. вариант — крутить эмиссию материала (опционально)")]
[SerializeField] private Renderer emissiveRenderer;
private static readonly int EmissionColorID = Shader.PropertyToID("_EmissionColor");
[Header("Mode")]
[SerializeField] private Mode mode = Mode.Blink;
[Header("Intensity")]
[SerializeField] private float minIntensity = 0f;
[SerializeField] private float maxIntensity = 1f;
[Header("Timings")]
[SerializeField] private float frequency = 2f; // Гц для Pulse/Noise, миганий/сек для Blink
[SerializeField, Range(0f, 1f)] private float duty = 0.2f; // Доля времени ON для Blink [0..1]
[SerializeField] private AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
[SerializeField] private bool useUnscaledTime = false;
[Header("Randomness (optional)")]
[SerializeField, Range(0f, 1f)] private float noiseAmplitude = 0.3f; // для Noise (0..1)
[SerializeField] private float noiseSpeed = 1.0f; // скорость «пламени»
[SerializeField] private Vector2 blinkJitter = new(-0.1f, 0.1f); // случайный сдвиг фазы Blink
[Header("Color (optional)")]
[SerializeField] private bool modulateColor = false;
[SerializeField] private Gradient colorOverCycle;
float blinkOffset;
Material _matInstance;
Color _baseEmission = Color.white;
private void Reset()
{
lights3D = GetComponentsInChildren<Light>();
lights2D = GetComponentsInChildren<Light2D>();
emissiveRenderer = GetComponent<Renderer>();
}
private void Awake()
{
if (emissiveRenderer && emissiveRenderer.sharedMaterial && _matInstance == null)
{
_matInstance = emissiveRenderer.material;
if (_matInstance.HasProperty(EmissionColorID))
{
_baseEmission = _matInstance.GetColor(EmissionColorID);
_matInstance.EnableKeyword("_EMISSION");
}
}
blinkOffset = Random.Range(blinkJitter.x, blinkJitter.y);
}
private void Update()
{
float time = useUnscaledTime ? Time.unscaledTime : Time.time;
float phase;
float k; // 0..1
switch (mode)
{
case Mode.Blink:
// пила с джиттером
phase = Mathf.Repeat((time + blinkOffset) * Mathf.Max(0.0001f, frequency), 1f);
k = phase < Mathf.Clamp01(duty) ? 1f : 0f;
break;
case Mode.Pulse:
// синус → 0..1
k = 0.5f * (1f + Mathf.Sin(time * Mathf.PI * 2f * frequency));
break;
case Mode.Noise:
// Perlin: базовый уровень + шум
float u = time * noiseSpeed;
float n = Mathf.PerlinNoise(u, 0.123f); // 0..1
float baseK = 0.5f * (1f + Mathf.Sin(time * Mathf.PI * 2f * frequency)); // мягкий пульс
k = Mathf.Clamp01(baseK * (1f - noiseAmplitude) + n * noiseAmplitude);
break;
case Mode.Curve:
// цикл 0..1 по частоте, кривой задаём форму
phase = Mathf.Repeat(time * Mathf.Max(0.0001f, frequency), 1f);
k = Mathf.Clamp01(curve.Evaluate(phase));
break;
default:
k = 1f; break;
}
float intensity = Mathf.Lerp(minIntensity, maxIntensity, k);
ApplyIntensity(intensity);
if (modulateColor && colorOverCycle != null)
{
ApplyColor(colorOverCycle.Evaluate(k));
}
}
private void ApplyIntensity(float value)
{
if (lights3D != null)
foreach (var t in lights3D)
if (t) t.intensity = value;
if (lights2D != null)
foreach (var t in lights2D)
if (t) t.intensity = value;
if (_matInstance && _matInstance.HasProperty(EmissionColorID))
_matInstance.SetColor(EmissionColorID, _baseEmission * value);
}
private void ApplyColor(Color c)
{
if (lights3D != null)
foreach (var t in lights3D)
if (t) t.color = c;
if (lights2D != null)
foreach (var t in lights2D)
if (t) t.color = c;
if (_matInstance && _matInstance.HasProperty(EmissionColorID))
_matInstance.SetColor(EmissionColorID, c * Mathf.Max(0.0001f, _matInstance.GetColor(EmissionColorID).maxColorComponent));
}
void OnDestroy()
{
if (_matInstance) Destroy(_matInstance);
}
}
}