Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/Language/CandidateParticle.cs
T

332 lines
12 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 System.Collections.Generic;
namespace AibisDream.MiniGame.Language
{
/// <summary>
/// 候选粒子(可交互的主要粒子)
/// </summary>
public class CandidateParticle : TextParticle
{
[Header("粒子状态(目标/非目标,颜色由 Manager 配置,可与红蓝解绑)")]
public bool isRed = false; // 当前是否为目标粒子(用于颜色/样式,可配成蓝)
public bool isOrange = false; // 是否受到效果影响(橙色)
public bool originalIsRed = false; // 原始是否为目标粒子(不变,用于字符逻辑)
public bool hasEffect = false; // 是否有效果
public bool isTemporaryRed = false; // 临时红色状态
[Header("连接")]
public List<CandidateParticle> connections = new List<CandidateParticle>();
[Header("效果")]
public float changeSpeedMultiplier = 1f;
public Vector2 vibrationOffset;
public float vibrationPhase;
public float effectTimer;
public float effectAlpha;
public float effectScale = 1f;
public float effectGlow;
[Header("焦虑效果")]
public float anxietyShakePhase;
public float anxietyShakeIntensity;
public float anxietyFloatPhase;
public float anxietyFloatSpeed;
public Vector2 anxietyShakeOffset;
public float anxietyFloatY;
[Header("非目标干扰效果")]
public float interferenceShakeIntensity = 0f;
public float interferenceShakeSpeed = 8f;
public float interferenceFloatAmplitude = 0.015f;
private float interferenceShakePhase;
private float interferenceFloatPhase;
private Vector2 interferenceShakeOffset;
private float interferenceFloatY;
[Header("波形关联")]
public float calmProgress = 0f; // 平静进度(0-1
public float dissolveProgress = 0f; // 消散进度(0-1
public WaveformPoint waveformPoint; // 关联的波形点
// 颜色配置(由Manager设置)
private Color targetColor = new Color(1f, 0.39f, 0.39f, 1f); // 目标粒子颜色
private Color nonTargetColor = new Color(0.2f, 0.78f, 1f, 1f); // 非目标粒子颜色
private Color propagationColor = new Color(1f, 0.59f, 0.2f, 1f); // 传播颜色
private Color calmColor = new Color(0.78f, 0.59f, 0.59f, 1f); // 平静后颜色
// 字体样式配置(由Manager设置)
private float targetFontSize = 3.5f;
private float nonTargetFontSize = 2.5f;
private bool targetBold = true;
private bool nonTargetBold = false;
protected override void Awake()
{
base.Awake();
baseAlpha = 0.6f; // 0-1 范围的透明度
probability = Random.Range(0.1f, 1f);
alpha = baseAlpha + probability * 0.4f; // 最大 1.0
size = nonTargetFontSize; // 默认使用非目标粒子大小
velocity = new Vector2(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f));
changeInterval = Random.Range(1f, 2.5f);
interferenceShakePhase = Random.Range(0f, Mathf.PI * 2f);
interferenceFloatPhase = Random.Range(0f, Mathf.PI * 2f);
if (textMesh != null)
{
textMesh.fontSize = size;
UpdateFontStyle();
}
}
protected override void Update()
{
base.Update();
// 更新效果动画
if (hasEffect)
{
UpdateEffectAnimation();
}
// 更新焦虑效果
if (isRed && (anxietyShakeIntensity > 0))
{
UpdateAnxietyEffect();
}
// 非目标粒子干扰抖动
if (!isRed && !isCalmed && interferenceShakeIntensity > 0)
{
UpdateInterferenceEffect();
}
}
private void UpdateEffectAnimation()
{
if (effectTimer > 0)
{
effectTimer -= Time.deltaTime;
// 振动效果
vibrationPhase += Time.deltaTime * 15f;
float vibrationIntensity = 0.02f;
vibrationOffset = new Vector2(
Mathf.Cos(vibrationPhase) * vibrationIntensity,
Mathf.Sin(vibrationPhase * 1.3f) * vibrationIntensity
);
// 透明度动画(0-1 范围)
effectAlpha = Mathf.Lerp(0.6f, 1f, (Mathf.Sin(Time.time * 3f) + 1f) / 2f);
// 缩放动画
effectScale = Mathf.Lerp(0.95f, 1.05f, (Mathf.Sin(Time.time * 4.5f) + 1f) / 2f);
// 发光强度
effectGlow = Mathf.Lerp(0.06f, 0.1f, (effectAlpha - 0.6f) / 0.4f);
}
}
private void UpdateAnxietyEffect()
{
// 根据平静进度减少抖动强度
float shakeIntensity = anxietyShakeIntensity * (1 - calmProgress) * 0.01f;
float floatAmplitude = 0.03f * (1 - calmProgress);
if (calmProgress < 0.9f)
{
anxietyShakePhase += Time.deltaTime * 10f;
anxietyFloatPhase += anxietyFloatSpeed;
}
// 计算抖动偏移
anxietyShakeOffset = new Vector2(
Mathf.Cos(anxietyShakePhase) * shakeIntensity + Mathf.Sin(anxietyShakePhase * 1.7f) * shakeIntensity * 0.5f,
Mathf.Sin(anxietyShakePhase * 1.3f) * shakeIntensity + Mathf.Cos(anxietyShakePhase * 0.9f) * shakeIntensity * 0.5f
);
// 计算漂浮偏移
anxietyFloatY = Mathf.Sin(anxietyFloatPhase) * floatAmplitude;
}
protected override void UpdateVisuals()
{
if (textMesh == null) return;
// 更新字体样式(大小和加粗)
UpdateFontStyle();
// 计算显示位置(叠加干扰抖动)
Vector3 displayOffset = (Vector3)(vibrationOffset + anxietyShakeOffset + interferenceShakeOffset)
+ Vector3.up * (anxietyFloatY + interferenceFloatY);
textMesh.transform.localPosition = displayOffset;
// 计算颜色和透明度
Color color = Color.white;
float displayAlpha = alpha;
if (hasEffect && effectTimer > 0)
{
displayAlpha = effectAlpha;
textMesh.transform.localScale = Vector3.one * effectScale;
}
// 根据消散进度减少透明度
displayAlpha *= (1 - dissolveProgress);
if (isRed)
{
// 目标粒子:根据平静进度从目标颜色过渡到平静颜色
float r = Mathf.Lerp(targetColor.r, calmColor.r, calmProgress);
float g = Mathf.Lerp(targetColor.g, calmColor.g, calmProgress);
float b = Mathf.Lerp(targetColor.b, calmColor.b, calmProgress);
color = new Color(r, g, b, displayAlpha);
}
else if (isOrange)
{
// 传播效果颜色
color = new Color(propagationColor.r, propagationColor.g, propagationColor.b, displayAlpha);
}
else
{
// 非目标粒子颜色
color = new Color(nonTargetColor.r, nonTargetColor.g, nonTargetColor.b, displayAlpha);
}
textMesh.color = color;
// 更新光晕
if (glowSprite != null)
{
glowSprite.color = new Color(color.r, color.g, color.b, color.a * 0.5f);
float glowScale = probability * 0.5f;
if (hasEffect)
glowScale += effectGlow;
glowSprite.transform.localScale = Vector3.one * glowScale;
}
}
/// <summary>
/// 目标粒子:chineseChars 随机单字;非目标粒子:从笑话/干扰短句字符中随机。
/// 使用 IsTarget 判断,与红蓝颜色解绑。
/// </summary>
protected override string GetNextDisplayChar()
{
if (TryGetOverridePoolChar(out string overrideChar))
return overrideChar;
return IsTarget ? GetRandomChar() : GetRandomCharFromPhrases();
}
/// <summary>
/// 是否为目标粒子(由 originalIsRed 表示,与显示颜色解绑)
/// </summary>
private bool IsTarget => originalIsRed;
private void UpdateInterferenceEffect()
{
interferenceShakePhase += Time.deltaTime * interferenceShakeSpeed;
interferenceFloatPhase += Time.deltaTime * interferenceShakeSpeed * 0.3f;
float intensity = interferenceShakeIntensity;
interferenceShakeOffset = new Vector2(
Mathf.Sin(interferenceShakePhase) * intensity
+ Mathf.Sin(interferenceShakePhase * 2.3f) * intensity * 0.4f,
Mathf.Cos(interferenceShakePhase * 1.7f) * intensity * 0.7f
+ Mathf.Sin(interferenceShakePhase * 0.6f) * intensity * 0.3f
);
interferenceFloatY = Mathf.Sin(interferenceFloatPhase) * interferenceFloatAmplitude;
}
public void SetInterferenceParams(float shakeIntensity, float shakeSpeed, float changeIntv, float floatAmplitude)
{
interferenceShakeIntensity = shakeIntensity;
interferenceShakeSpeed = shakeSpeed;
interferenceFloatAmplitude = floatAmplitude;
if (!isRed)
{
changeInterval = Mathf.Max(0.05f, changeIntv * Random.Range(0.7f, 1.3f));
}
}
public void InitializeAnxietyEffect()
{
anxietyShakePhase = Random.Range(0f, Mathf.PI * 2f);
anxietyShakeIntensity = Random.Range(2f, 4f);
anxietyFloatPhase = Random.Range(0f, Mathf.PI * 2f);
anxietyFloatSpeed = Random.Range(0.02f, 0.04f);
}
public void ApplyEffect(float duration = 1f)
{
hasEffect = true;
effectTimer = duration;
isOrange = true;
isRed = false;
changeSpeedMultiplier = 3f;
vibrationPhase = Random.Range(0f, Mathf.PI * 2f);
}
public void RemoveEffect()
{
hasEffect = false;
isOrange = false;
isRed = false;
changeSpeedMultiplier = 1f;
vibrationOffset = Vector2.zero;
effectTimer = 0;
}
/// <summary>
/// 设置粒子颜色配置
/// </summary>
public void SetColors(Color target, Color nonTarget, Color propagation, Color calm)
{
targetColor = target;
nonTargetColor = nonTarget;
propagationColor = propagation;
calmColor = calm;
}
/// <summary>
/// 设置字体样式配置
/// </summary>
public void SetFontStyles(float targetSize, float nonTargetSize, bool targetIsBold, bool nonTargetIsBold)
{
targetFontSize = targetSize;
nonTargetFontSize = nonTargetSize;
targetBold = targetIsBold;
nonTargetBold = nonTargetIsBold;
// 立即应用
if (textMesh != null)
{
UpdateFontStyle();
}
}
/// <summary>
/// 更新字体样式(根据粒子状态)
/// </summary>
private void UpdateFontStyle()
{
if (textMesh == null) return;
// 根据是否为目标粒子设置大小和加粗
if (isRed)
{
textMesh.fontSize = targetFontSize;
textMesh.fontStyle = targetBold ? TMPro.FontStyles.Bold : TMPro.FontStyles.Normal;
}
else
{
textMesh.fontSize = nonTargetFontSize;
textMesh.fontStyle = nonTargetBold ? TMPro.FontStyles.Bold : TMPro.FontStyles.Normal;
}
}
}
}