144 lines
5.4 KiB
C#
144 lines
5.4 KiB
C#
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;
|
||
|
||
private float _blinkOffset;
|
||
private Material _matInstance;
|
||
private 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);
|
||
}
|
||
}
|
||
}
|