This commit is contained in:
2025-05-27 19:20:03 +08:00
parent b28044f602
commit f23affbabd
2 changed files with 200 additions and 0 deletions
+189
View File
@@ -0,0 +1,189 @@
using UnityEngine;
[ExecuteInEditMode]
[RequireComponent(typeof(LineRenderer))]
public class RobotECGWave : MonoBehaviour
{
public enum WaveType
{
RobotECG,
Sine,
Triangle,
Square,
HumanECG
}
[Header("波形设置")]
public WaveType waveType = WaveType.RobotECG;
public float waveHeight = 1f;
public float waveWidth = 10f;
public float waveStretch = 1f;
public float speed = 2f;
[Header("绘图设置")]
public int resolution = 300;
public float updateInterval = 0.02f;
private LineRenderer lineRenderer;
private Vector3[] points;
private float timer = 0f;
private float lastWidth = -1f;
private int lastResolution = -1;
private float phaseOffset = 0f;
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 Update()
{
Init();
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);
}
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.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; // 静息段
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 255e27a83db9041409f9a2deb08fcc9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: