using UnityEngine;
/// 混沌裂缝传送门:主层(静态椭圆框)+ 内层(原地波动),支持白/红/蓝三色切换。
[ExecuteAlways]
public class RiftPortalVisual : MonoBehaviour
{
[Header("裂缝渲染层(主层 + 内层)")]
[SerializeField] private Renderer[] riftRenderers;
[SerializeField] private Transform innerLayer;
[Header("颜色状态(配色与水晶矿一致)")]
[SerializeField] private Color currentColor = Color.white;
[SerializeField] private Color neutralColor = Color.white;
[SerializeField] private Color blueColor = new Color(0.1f, 0.65f, 1f, 1f);
[SerializeField] private Color redColor = new Color(1f, 0.12f, 0.08f, 1f);
[Header("原地波动动画(仅运行时,无位移无旋转)")]
[SerializeField, Min(0f)] private float pulseSpeed = 2.2f;
[Tooltip("内层整体缩放的呼吸幅度")]
[SerializeField, Range(0f, 0.2f)] private float pulseAmplitude = 0.04f;
[Tooltip("亮度明暗波动幅度 0~1")]
[SerializeField, Range(0f, 1f)] private float glowPulseAmount = 0.25f;
private MaterialPropertyBlock propertyBlock;
private Vector3 innerBaseScale;
private bool baseScaleCached;
public Color CurrentColor => currentColor;
private void OnEnable() => ApplyColor();
private void OnValidate() => ApplyColor();
private void Reset() => CollectRenderers();
public void SetRiftColor(Color color)
{
currentColor = color;
ApplyColor();
}
/// teamId: 0=蓝, 1=红, 其他=白(中立),与水晶矿争夺语义一致。
public void SetTeam(int teamId)
{
SetRiftColor(teamId == 0 ? blueColor : teamId == 1 ? redColor : neutralColor);
}
private void ApplyColor(float brightness = 1f)
{
if (riftRenderers == null || riftRenderers.Length == 0)
{
CollectRenderers();
}
if (riftRenderers == null) return;
propertyBlock ??= new MaterialPropertyBlock();
Color tint = new Color(
currentColor.r * brightness,
currentColor.g * brightness,
currentColor.b * brightness,
currentColor.a);
foreach (Renderer renderer in riftRenderers)
{
if (renderer == null) continue;
renderer.GetPropertyBlock(propertyBlock);
// Legacy Shaders/Particles/Additive 用 _TintColor 作为颜色入口
propertyBlock.SetColor("_TintColor", tint);
propertyBlock.SetColor("_Color", tint);
renderer.SetPropertyBlock(propertyBlock);
}
}
private void CollectRenderers()
{
riftRenderers = GetComponentsInChildren(true);
}
private void Update()
{
if (!Application.isPlaying) return;
float t = Time.time;
float wave = Mathf.Sin(t * pulseSpeed);
// 内层整体缩放的轻微呼吸(围绕自身中心,原地)
if (innerLayer != null)
{
if (!baseScaleCached)
{
innerBaseScale = innerLayer.localScale;
baseScaleCached = true;
}
float pulse = 1f + wave * pulseAmplitude;
innerLayer.localScale = new Vector3(
innerBaseScale.x * pulse,
innerBaseScale.y * pulse,
innerBaseScale.z);
}
// 亮度明暗波动(原地能量涌动)
float brightness = 1f - glowPulseAmount * (0.5f - 0.5f * wave);
ApplyColor(brightness);
}
}