Danro/Assets/Scripts/Behaviour/LightDimmer.cs

166 lines
6.0 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 System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
[RequireComponent(typeof(Collider2D))]
public class LightDimmer : MonoBehaviour
{
[Tooltip("Если не указан, будет использован Collider2D на этом же объекте.")]
[SerializeField] private Collider2D targetCollider;
[Tooltip("Тег игрока (используется для поиска Transform игрока)")]
[SerializeField] private string playerTag;
[Tooltip("Если хотите явно назначить конкретный Light2D для этого экземпляра, укажите его здесь (приоритет).")]
[SerializeField] private Light2D[] lights;
[Tooltip("Интенсивность света у минимального X (bounds.min.x)")]
[SerializeField] private float startXIntensity;
[Tooltip("Интенсивность света у максимального X (bounds.max.x)")]
[SerializeField] private float endXIntensity;
[Tooltip("Опционально: сглаживание изменения (0 мгновенно, >0 — скорость, единицы: интенсивность/сек)")]
[SerializeField] [Min(0)] private float smoothing;
private Transform playerTransform;
// Храним все коллайдеры игрока, которые в данный момент пересекают триггер
private readonly HashSet<Collider2D> playerColliders = new HashSet<Collider2D>();
private float boundsMinX;
private float boundsMaxX;
private void OnValidate()
{
if (targetCollider != null)
{
UpdateBounds();
}
if (string.IsNullOrEmpty(playerTag)) playerTag = "Player";
}
private void OnEnable()
{
if (targetCollider == null)
targetCollider = GetComponent<Collider2D>();
if (targetCollider != null)
{
UpdateBounds();
}
if (string.IsNullOrEmpty(playerTag)) playerTag = "Player";
var playerObj = GameObject.FindGameObjectWithTag(playerTag);
if (playerObj != null)
playerTransform = playerObj.transform;
}
private void Start()
{
if (targetCollider == null)
{
targetCollider = GetComponent<Collider2D>();
}
UpdateBounds();
if (string.IsNullOrEmpty(playerTag)) playerTag = "Player";
}
private void Update()
{
// Нужна ссылка на игрока и хотя бы один свет и collider
if (!playerTransform || lights == null || lights.Length == 0 || targetCollider == null)
return;
// Проверяем, что игрок действительно внутри триггера (с учётом возможной множественной геометрии)
bool playerInside = playerColliders.Count > 0;
if (!playerInside)
return;
Vector3 playerPos = playerTransform.position;
// Дополнительная страховка: проверяем AABB bounds
if (!targetCollider.bounds.Contains(playerPos))
return;
float playerX = playerPos.x;
float t = 0f;
if (!Mathf.Approximately(boundsMaxX, boundsMinX))
{
t = Mathf.InverseLerp(boundsMinX, boundsMaxX, playerX);
t = Mathf.Clamp01(t);
}
// Интерполируем интенсивность между startXIntensity и endXIntensity
float desiredForPosition = Mathf.Lerp(startXIntensity, endXIntensity, t);
for (int i = 0; i < lights.Length; i++)
{
var light2D = lights[i];
if (!light2D) continue;
if (smoothing <= 0f)
{
light2D.intensity = desiredForPosition;
}
else
{
light2D.intensity = Mathf.MoveTowards(light2D.intensity, desiredForPosition, smoothing * Time.deltaTime);
}
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (!other.CompareTag(playerTag)) return;
// Запоминаем коллайдер игрока
playerColliders.Add(other);
// Сохраняем Transform игрока (на случай, если раньше не найден)
if (playerTransform == null)
playerTransform = other.transform;
}
private void OnTriggerExit2D(Collider2D other)
{
if (!other.CompareTag(playerTag)) return;
// Убираем коллайдер из множества; если множество пустое — игрок полностью вышел
playerColliders.Remove(other);
// Не затираем playerTransform, оставляем ссылку (чтобы можно было продолжать вычисления при следующем входе).
// Если нужно — можно дополнительно реагировать на полное выход игрока (playerColliders.Count == 0).
}
private void UpdateBounds()
{
var b = targetCollider.bounds;
boundsMinX = b.min.x;
boundsMaxX = b.max.x;
}
void OnDrawGizmosSelected()
{
if (targetCollider == null) return;
var b = targetCollider.bounds;
Gizmos.color = Color.yellow;
Gizmos.DrawLine(new Vector3(b.min.x, b.min.y, 0f), new Vector3(b.max.x, b.min.y, 0f));
Gizmos.DrawLine(new Vector3(b.max.x, b.min.y, 0f), new Vector3(b.max.x, b.max.y, 0f));
Gizmos.DrawLine(new Vector3(b.max.x, b.max.y, 0f), new Vector3(b.min.x, b.max.y, 0f));
Gizmos.DrawLine(new Vector3(b.min.x, b.max.y, 0f), new Vector3(b.min.x, b.min.y, 0f));
if (playerTransform != null)
{
Gizmos.color = Color.cyan;
Vector3 p = playerTransform.position;
Gizmos.DrawSphere(new Vector3(p.x, p.y, 0f), 0.05f);
}
}
}