Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/SalesSystem/ProcessorLightController.cs
T

472 lines
15 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.Events;
using System.Collections.Generic;
using DG.Tweening;
namespace AibisDream.MiniGame.HuoShan
{
/// <summary>
/// 处理器灯光控制器 - 管理多个处理器灯的显示
/// 功能:
/// - 根据滑片位置或索引控制特定处理器灯亮起
/// - 提供灯光明暗、闪烁、颜色变化效果
/// - 支持顺序激活多个处理器
/// </summary>
public class ProcessorLightController : MonoBehaviour
{
[System.Serializable]
public class ProcessorLightConfig
{
public GameObject lightObject;
public Light lightComponent;
public Renderer lightRenderer;
public Color normalColor = Color.gray;
public Color activeColor = new Color(0.3f, 0.9f, 0.55f);
public float intensity = 1f;
public float blinkSpeed = 1f;
public float fadeInDuration = 0.3f;
public string emissionProperty = "_EmissionColor";
public int segmentIndex = 0; // 对应的段索引
public float segmentStartAngle = 0f; // 该段的开始角度
public float segmentEndAngle = 30f; // 该段的结束角度
}
[Header("处理器配置")]
[Tooltip("处理器灯光配置列表")]
[SerializeField] private List<ProcessorLightConfig> processorLights = new List<ProcessorLightConfig>();
[Tooltip("默认激活持续时间(秒)")]
[SerializeField] private float defaultActiveDuration = 2f;
[Tooltip("灯光强度曲线(用于闪烁效果)")]
[SerializeField] private AnimationCurve intensityCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
[Header("全局设置")]
[Tooltip("等离子体发光影响所有处理器灯")]
[SerializeField] private bool plasmaAffectsAll = false;
[Tooltip("等离子体发光强度")]
[SerializeField] private float plasmaGlowIntensity = 0.5f;
[Tooltip("等离子体发光颜色")]
[SerializeField] private Color plasmaGlowColor = new Color(0.3f, 0.9f, 0.55f);
[Header("滑片联动")]
[Tooltip("滑片控制器引用(用于监听位置变化)")]
[SerializeField] private SliderController sliderController;
[Tooltip("滑片位置变化时自动更新处理器灯")]
[SerializeField] private bool autoUpdateFromSlider = true;
[Tooltip("滑片弧度到处理器索引的映射表,按角度排序")]
[SerializeField] private AnimationCurve angleToProcessorCurve = new AnimationCurve(
new Keyframe(0f, 0f),
new Keyframe(1f, 11f)
);
[Header("事件")]
[Tooltip("处理器灯激活时触发")]
public UnityEvent<int> onProcessorActivated;
[Tooltip("所有处理器灯关闭时触发")]
public UnityEvent onAllLightsOff;
private Dictionary<int, ProcessorLightConfig> _processorMap = new Dictionary<int, ProcessorLightConfig>();
private List<Tween> _activeTweens = new List<Tween>();
private bool _isInitialized = false;
private int _lastActiveProcessor = -1;
#region 生命周期
private void Awake()
{
InitializeProcessorMap();
}
private void OnEnable()
{
if (sliderController != null && autoUpdateFromSlider)
{
sliderController.onSliderPositionChanged.AddListener(OnSliderPositionChanged);
}
}
private void OnDisable()
{
if (sliderController != null)
{
sliderController.onSliderPositionChanged.RemoveListener(OnSliderPositionChanged);
}
// 清理所有Tweens
foreach (var tween in _activeTweens)
{
if (tween != null && tween.IsActive())
{
tween.Kill();
}
}
_activeTweens.Clear();
}
#endregion
#region 初始化
private void InitializeProcessorMap()
{
_processorMap.Clear();
foreach (var config in processorLights)
{
if (config.lightObject != null)
{
// 查找灯光组件
if (config.lightComponent == null)
{
config.lightComponent = config.lightObject.GetComponent<Light>();
}
// 查找渲染器
if (config.lightRenderer == null)
{
config.lightRenderer = config.lightObject.GetComponent<Renderer>();
}
// 初始化为关闭状态
SetLightState(config, false, 0f);
_processorMap[config.segmentIndex] = config;
}
}
_isInitialized = true;
Debug.Log($"ProcessorLightController: 初始化完成,共{processorLights.Count}个处理器灯");
}
#endregion
#region 滑片位置监听
private void OnSliderPositionChanged(float normalizedPosition)
{
if (!autoUpdateFromSlider) return;
// 映射滑片位置到处理器索引
int processorIndex = GetProcessorIndexFromSlider(normalizedPosition);
// 如果到达新的处理器段,激活对应的灯
if (processorIndex != _lastActiveProcessor)
{
ActivateProcessor(processorIndex);
_lastActiveProcessor = processorIndex;
}
}
/// <summary>
/// 将滑片标准化位置(0-1)映射到处理器索引(0-processorCount-1
/// </summary>
public int GetProcessorIndexFromSlider(float normalizedPosition)
{
// 使用AnimationCurve进行映射
float processorValue = angleToProcessorCurve.Evaluate(normalizedPosition);
return Mathf.RoundToInt(processorValue);
}
#endregion
#region 处理器灯光控制
/// <summary>
/// 根据角度激活对应的处理器灯
/// </summary>
public void ActivateProcessorByAngle(float angle)
{
float normalizedAngle = angle / 360f;
int processorIndex = GetProcessorIndexFromSlider(normalizedAngle);
ActivateProcessor(processorIndex);
}
/// <summary>
/// 激活指定索引的处理器灯
/// </summary>
public void ActivateProcessor(int processorIndex, float duration = -1f)
{
if (!_isInitialized)
{
InitializeProcessorMap();
}
if (duration < 0)
{
duration = defaultActiveDuration;
}
// 先关闭所有灯
DeactivateAllProcessors(0.2f);
// 检查索引是否有效
if (processorIndex < 0 || processorIndex >= processorLights.Count)
{
Debug.LogWarning($"ProcessorLightController: 处理器索引{processorIndex}超出范围");
return;
}
// 获取配置
ProcessorLightConfig config = null;
foreach (var kvp in _processorMap)
{
if (kvp.Key == processorIndex)
{
config = kvp.Value;
break;
}
}
if (config != null)
{
// 激活灯光
SetLightState(config, true, duration);
// 触发事件
onProcessorActivated?.Invoke(processorIndex);
Debug.Log($"ProcessorLightController: 激活处理器{processorIndex}");
}
else
{
Debug.LogWarning($"ProcessorLightController: 找不到处理器索引{processorIndex}的配置");
}
}
/// <summary>
/// 关闭所有处理器灯
/// </summary>
public void DeactivateAllProcessors(float fadeOutDuration = 0.3f)
{
foreach (var config in processorLights)
{
SetLightState(config, false, fadeOutDuration);
}
_lastActiveProcessor = -1;
onAllLightsOff?.Invoke();
}
/// <summary>
/// 显示异常段的处理器灯(闪烁效果)
/// </summary>
public void ShowAnomalyProcessor(int processorIndex)
{
ProcessorLightConfig config = FindProcessorConfig(processorIndex);
if (config != null)
{
// 闪烁效果
FlashLight(config, Color.red, 2f, 3);
}
}
/// <summary>
/// 设置灯光状态
/// </summary>
private void SetLightState(ProcessorLightConfig config, bool isActive, float transitionDuration)
{
if (config.lightObject == null) return;
// 设置灯光组件
if (config.lightComponent != null)
{
float targetIntensity = isActive ? config.intensity : 0f;
// 使用Tween实现平滑过渡
Tweener intensityTween = DOTween.To(
() => config.lightComponent.intensity,
value => config.lightComponent.intensity = value,
targetIntensity,
transitionDuration
).SetEase(Ease.OutQuad);
_activeTweens.Add(intensityTween);
}
// 设置渲染器发光
if (config.lightRenderer != null)
{
Color targetColor = isActive ? config.activeColor : config.normalColor;
// 对于使用Emission的材质
Material material = config.lightRenderer.material;
if (!string.IsNullOrEmpty(config.emissionProperty))
{
int propertyID = Shader.PropertyToID(config.emissionProperty);
Tweener colorTween = DOTween.To(
() => material.GetColor(propertyID),
value => material.SetColor(propertyID, value),
targetColor,
transitionDuration
).SetEase(Ease.OutQuad);
_activeTweens.Add(colorTween);
}
// 设置基础颜色
Tweener baseColorTween = DOTween.To(
() => config.lightRenderer.material.color,
value => config.lightRenderer.material.color = value,
targetColor,
transitionDuration
).SetEase(Ease.OutQuad);
_activeTweens.Add(baseColorTween);
}
// 更新GameObject状态
config.lightObject.SetActive(true);
}
/// <summary>
/// 灯光闪烁效果
/// </summary>
private void FlashLight(ProcessorLightConfig config, Color flashColor, float duration, int flashCount)
{
// 先停止之前的动画
config.lightObject.GetComponent<Renderer>()?.material?.DOComplete();
// 执行闪烁
if (config.lightComponent != null)
{
Sequence flashSequence = DOTween.Sequence();
for (int i = 0; i < flashCount; i++)
{
flashSequence.Append(config.lightComponent.DOIntensity(config.intensity * 2f, duration / (flashCount * 2)));
flashSequence.Append(config.lightComponent.DOIntensity(config.intensity, duration / (flashCount * 2)));
}
_activeTweens.Add(flashSequence);
}
if (config.lightRenderer != null)
{
Color originalColor = config.lightRenderer.material.color;
Sequence colorSequence = DOTween.Sequence();
for (int i = 0; i < flashCount; i++)
{
colorSequence.Append(config.lightRenderer.material.DOColor(flashColor, duration / (flashCount * 2)));
colorSequence.Append(config.lightRenderer.material.DOColor(originalColor, duration / (flashCount * 2)));
}
_activeTweens.Add(colorSequence);
}
}
/// <summary>
/// 查找处理器配置
/// </summary>
private ProcessorLightConfig FindProcessorConfig(int processorIndex)
{
if (_processorMap.TryGetValue(processorIndex, out var config))
{
return config;
}
foreach (var lightConfig in processorLights)
{
if (lightConfig.segmentIndex == processorIndex)
{
return lightConfig;
}
}
return null;
}
#endregion
#region 映射配置
/// <summary>
/// 更新角度到处理器的映射曲线
/// </summary>
public void UpdateAngleToProcessorCurve(AnimationCurve curve)
{
angleToProcessorCurve = curve;
}
/// <summary>
/// 根据滑片控制器自动配置映射
/// </summary>
public void AutoConfigureMapping()
{
if (sliderController == null) return;
int segmentCount = sliderController.GetCurrentSegment();
if (segmentCount <= 0) return;
// 创建线性映射
Keyframe[] keys = new Keyframe[processorLights.Count];
float step = 1f / (processorLights.Count - 1);
for (int i = 0; i < processorLights.Count; i++)
{
keys[i] = new Keyframe(i * step, i);
}
angleToProcessorCurve = new AnimationCurve(keys);
}
#endregion
#region 公共方法
/// <summary>
/// 获取活动中的处理器索引
/// </summary>
public int GetActiveProcessor()
{
return _lastActiveProcessor;
}
/// <summary>
/// 获取处理器数量
/// </summary>
public int GetProcessorCount()
{
return processorLights.Count;
}
/// <summary>
/// 设置等离子体发光影响
/// </summary>
public void SetPlasmaGlow(float intensity, Color? color = null)
{
plasmaGlowIntensity = intensity;
if (color.HasValue)
{
plasmaGlowColor = color.Value;
}
}
/// <summary>
/// 重置所有灯光
/// </summary>
public void Reset()
{
DeactivateAllProcessors();
_lastActiveProcessor = -1;
}
/// <summary>
/// 配置处理器灯光数据
/// </summary>
public void ConfigureProcessorLights(List<ProcessorLightConfig> configs)
{
processorLights = configs;
InitializeProcessorMap();
}
#endregion
}
}