Files
aibis-dream/Assets/Scripts/FixSystemNew/RobotECGWave.cs
T
2025-06-03 21:50:35 +08:00

452 lines
13 KiB
C#

using UnityEngine;
[ExecuteInEditMode]
[RequireComponent(typeof(LineRenderer))]
public class RobotECGWave : MonoBehaviour
{
public enum WaveType
{
RobotECG,
Sine,
Triangle,
Square,
HumanECG,
Emergency,
Noise,
Abnormal,
Warning,
Flatline
}
[Header("波形设置")]
public WaveType waveType = WaveType.RobotECG;
public float waveHeight = 1f;
public float waveWidth = 10f;
public float waveStretch = 1f;
public float speed = 2f;
[Header("颜色设置")]
[SerializeField] private Color[] normalColors = new Color[4];
[SerializeField] private Color[] warningColors = new Color[4];
[SerializeField] private Color[] emergencyColors = new Color[4];
[Header("绘图设置")]
public int resolution = 300;
public float updateInterval = 0.02f;
[Header("发光点设置")]
public SpriteRenderer glowPoint;
public Color glowColor = Color.red;
public float glowSize = 0.1f;
[Header("噪音设置")]
public float noiseAmplitude = 0.5f;
public float targetWaveformNoiseAmplitude = 0.1f;
private LineRenderer lineRenderer;
private Vector3[] points;
private float timer = 0f;
private float lastWidth = -1f;
private int lastResolution = -1;
private float phaseOffset = 0f;
private void Start()
{
Init();
SetupGlowPoint();
}
void OnEnable()
{
Init();
}
void Init()
{
if (lineRenderer == null)
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.useWorldSpace = true;
if (points == null || resolution != lastResolution || waveWidth != lastWidth)
{
points = new Vector3[resolution];
lineRenderer.positionCount = resolution;
lastResolution = resolution;
lastWidth = waveWidth;
}
}
void SetupGlowPoint()
{
if (glowPoint == null)
{
GameObject glowObj = new GameObject("GlowPoint");
glowObj.transform.SetParent(transform);
glowPoint = glowObj.AddComponent<SpriteRenderer>();
// 创建一个简单的圆形精灵
Texture2D texture = new Texture2D(32, 32);
Color[] colors = new Color[32 * 32];
for (int i = 0; i < colors.Length; i++)
{
float x = (i % 32) / 31f;
float y = (i / 32) / 31f;
float distance = Vector2.Distance(new Vector2(x, y), new Vector2(0.5f, 0.5f));
colors[i] = new Color(1, 1, 1, Mathf.Clamp01(1 - distance * 2));
}
texture.SetPixels(colors);
texture.Apply();
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 32, 32), new Vector2(0.5f, 0.5f));
glowPoint.sprite = sprite;
}
glowPoint.color = glowColor;
glowPoint.transform.localScale = Vector3.one * glowSize;
}
void Update()
{
if (Application.isPlaying)
{
timer += Time.deltaTime;
if (timer >= updateInterval)
{
timer = 0f;
phaseOffset += updateInterval * speed;
UpdateWave();
}
}
else
{
phaseOffset = Time.realtimeSinceStartup * speed;
UpdateWave();
}
}
void UpdateWave()
{
Vector3 origin = transform.position;
Quaternion rotation = transform.rotation;
for (int i = 0; i < resolution; i++)
{
float x = ((float)i / resolution) * waveWidth;
float timeOffset = (x / waveWidth) * waveStretch + phaseOffset;
float waveValue = GetWaveValue(timeOffset % 1.0f);
Vector3 localPos = new Vector3(x, waveValue * waveHeight, 0f);
points[i] = origin + rotation * localPos;
}
if (lineRenderer != null)
lineRenderer.SetPositions(points);
// 更新发光点位置
if (glowPoint != null)
{
Vector3 lastPoint = points[resolution - 1];
glowPoint.transform.position = lastPoint;
}
}
public void SetWaveType(WaveType type)
{
waveType = type;
// switch (type)
// {
// case WaveType.RobotECG:
// SetWaveColors(normalColors);
// break;
// case WaveType.Noise:
// SetWaveColors(emergencyColors);
// break;
// case WaveType.Abnormal:
// SetWaveColors(warningColors);
// break;
// }
}
private void SetWaveColors(Color[] colors)
{
if (lineRenderer != null && colors != null && colors.Length > 0)
{
Gradient gradient = new Gradient();
GradientColorKey[] colorKeys = new GradientColorKey[colors.Length];
GradientAlphaKey[] alphaKeys = new GradientAlphaKey[2];
for (int i = 0; i < colors.Length; i++)
{
colorKeys[i] = new GradientColorKey(colors[i], i / (float)(colors.Length - 1));
}
alphaKeys[0] = new GradientAlphaKey(1f, 0f);
alphaKeys[1] = new GradientAlphaKey(1f, 1f);
gradient.SetKeys(colorKeys, alphaKeys);
lineRenderer.colorGradient = gradient;
}
}
float GetWaveValue(float time)
{
switch (waveType)
{
case WaveType.Sine:
return Mathf.Sin(time * Mathf.PI * 2f);
case WaveType.Triangle:
return 2f * Mathf.Abs(2f * (time - Mathf.Floor(time + 0.5f))) - 1f;
case WaveType.Square:
return Mathf.Sign(Mathf.Sin(time * Mathf.PI * 2f));
case WaveType.HumanECG:
return GenerateHumanECGShape(time);
case WaveType.Emergency:
return GenerateEmergencyShape(time);
case WaveType.Noise:
return GenerateNoiseShape(time);
case WaveType.Abnormal:
return GenerateAbnormalShape(time);
case WaveType.Warning:
return GenerateWarningShape(time);
case WaveType.Flatline:
return 0f; // 返回0表示一条直线
case WaveType.RobotECG:
default:
return GenerateRobotECGShape(time);
}
}
float GenerateRobotECGShape(float time)
{
float t = time % 1.0f;
float baseValue = 0f;
if (t < 0.10f)
{
// 上升锯齿:锯齿线性上升
baseValue = (t / 0.10f) + Mathf.PingPong(t * 80f, 0.1f);
}
else if (t < 0.20f)
{
// 高电平方波 + 高频扰动
baseValue = 1f + Mathf.PingPong(t * 120f, 0.1f);
}
else if (t < 0.30f)
{
// 快速下降:线性下降带锯齿
baseValue = Mathf.Lerp(1f, -0.8f, (t - 0.20f) / 0.10f) + Mathf.PingPong(t * 100f, 0.05f);
}
else if (t < 0.40f)
{
// 低电平方波 + 微扰动
baseValue = -0.8f + Mathf.PingPong(t * 60f, 0.05f);
}
else
{
// 平缓底噪,锯齿叠加轻扰动
baseValue = Mathf.Sin(t * 80f) * 0.05f + Mathf.PingPong(t * 10f, 0.02f);
}
return baseValue;
}
float GenerateHumanECGShape(float time)
{
float t = time % 1.0f;
if (t < 0.1f)
return Mathf.Lerp(0f, 0.1f, t / 0.1f); // P 波上升
else if (t < 0.2f)
return Mathf.Lerp(0.1f, 0f, (t - 0.1f) / 0.1f); // P 波下降
else if (t < 0.22f)
return Mathf.Lerp(0f, -0.15f, (t - 0.2f) / 0.02f); // Q 波
else if (t < 0.26f)
return Mathf.Lerp(-0.15f, 1f, (t - 0.22f) / 0.04f); // R 波快速上升
else if (t < 0.30f)
return Mathf.Lerp(1f, -0.3f, (t - 0.26f) / 0.04f); // S 波下降
else if (t < 0.35f)
return Mathf.Lerp(-0.3f, 0f, (t - 0.30f) / 0.05f); // 回到0线
else if (t < 0.5f)
return Mathf.Lerp(0f, 0.4f, (t - 0.35f) / 0.15f); // T 波上升
else if (t < 0.65f)
return Mathf.Lerp(0.4f, 0f, (t - 0.5f) / 0.15f); // T 波下降
else
return 0f; // 静息段
}
float GenerateEmergencyShape(float time)
{
float t = time % 1.0f;
float baseValue = 0f;
// 使用多个正弦波叠加来创造不规则波形
float irregularity = Mathf.Sin(t * 20f) * 0.2f +
Mathf.Sin(t * 35f) * 0.15f +
Mathf.Sin(t * 50f) * 0.1f;
if (t < 0.15f)
{
// 快速上升段
baseValue = Mathf.Lerp(0f, 1.2f, t / 0.15f) + irregularity;
}
else if (t < 0.25f)
{
// 剧烈波动段
baseValue = 1.2f + Mathf.Sin(t * 100f) * 0.3f + irregularity;
}
else if (t < 0.35f)
{
// 快速下降段
baseValue = Mathf.Lerp(1.2f, -0.8f, (t - 0.25f) / 0.1f) + irregularity;
}
else if (t < 0.45f)
{
// 不规则波动段
baseValue = -0.8f + Mathf.Sin(t * 80f) * 0.4f + irregularity;
}
else if (t < 0.55f)
{
// 快速上升段
baseValue = Mathf.Lerp(-0.8f, 0.8f, (t - 0.45f) / 0.1f) + irregularity;
}
else if (t < 0.65f)
{
// 高频震荡段
baseValue = 0.8f + Mathf.Sin(t * 120f) * 0.2f + irregularity;
}
else if (t < 0.75f)
{
// 快速下降段
baseValue = Mathf.Lerp(0.8f, -0.5f, (t - 0.65f) / 0.1f) + irregularity;
}
else
{
// 不规则底噪段
baseValue = -0.5f + Mathf.Sin(t * 60f) * 0.3f + irregularity;
}
// 添加随机扰动
baseValue += Mathf.PerlinNoise(t * 100f, Time.time) * 0.1f;
return baseValue;
}
float GenerateNoiseShape(float time)
{
float t = time % 1.0f;
// 使用纯随机值生成噪音
float noise = Random.Range(-noiseAmplitude, noiseAmplitude);
// 确保波形在合理范围内
return Mathf.Clamp(noise, -1f, 1f);
}
float GenerateAbnormalShape(float time)
{
float t = time % 1.0f;
float baseValue = GenerateRobotECGShape(t);
// 添加随机抖动
if (Random.value < 0.1f) // 10%的概率发生抖动
{
float jitterAmount = Random.Range(-0.3f, 0.3f);
baseValue += jitterAmount;
}
// 添加周期性波动
float periodicWave = Mathf.Sin(t * 20f) * 0.1f;
baseValue += periodicWave;
return Mathf.Clamp(baseValue, -1f, 1f);
}
float GenerateWarningShape(float time)
{
float t = time % 1.0f;
float baseValue = 0f;
// 警告状态的特征波形
if (t < 0.15f)
{
// 快速上升段,带有轻微抖动
baseValue = Mathf.Lerp(0f, 1.2f, t / 0.15f) + Mathf.Sin(t * 100f) * 0.1f;
}
else if (t < 0.25f)
{
// 高频震荡段
baseValue = 1.2f + Mathf.Sin(t * 200f) * 0.2f;
}
else if (t < 0.35f)
{
// 快速下降段,带有不规则波动
baseValue = Mathf.Lerp(1.2f, -0.5f, (t - 0.25f) / 0.1f) + Mathf.Sin(t * 150f) * 0.15f;
}
else if (t < 0.45f)
{
// 不规则波动段
baseValue = -0.5f + Mathf.Sin(t * 80f) * 0.3f + Mathf.Sin(t * 120f) * 0.2f;
}
else if (t < 0.55f)
{
// 快速上升段,带有高频抖动
baseValue = Mathf.Lerp(-0.5f, 0.8f, (t - 0.45f) / 0.1f) + Mathf.Sin(t * 180f) * 0.15f;
}
else if (t < 0.65f)
{
// 剧烈波动段
baseValue = 0.8f + Mathf.Sin(t * 250f) * 0.25f + Mathf.Sin(t * 150f) * 0.15f;
}
else if (t < 0.75f)
{
// 快速下降段,带有不规则波动
baseValue = Mathf.Lerp(0.8f, -0.3f, (t - 0.65f) / 0.1f) + Mathf.Sin(t * 200f) * 0.2f;
}
else
{
// 不规则底噪段,增加波动频率
baseValue = -0.3f + Mathf.Sin(t * 100f) * 0.2f + Mathf.Sin(t * 150f) * 0.15f;
}
// 添加随机扰动,增加不稳定性
if (Random.value < 0.2f) // 20%的概率发生较大抖动
{
float jitterAmount = Random.Range(-0.3f, 0.3f);
baseValue += jitterAmount;
}
// 添加随机尖峰,增加警告感
if (Random.value < 0.1f) // 10%的概率出现尖峰
{
float spikeAmount = Random.Range(0.2f, 0.4f);
baseValue += spikeAmount;
}
// 确保波形在合理范围内
return Mathf.Clamp(baseValue, -1f, 1f);
}
}