EnergyEfficiencyManagement/Assets/Zion/Scripts/HeatMap/WindTurbineHeatSimulator.cs

305 lines
10 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.

// WindTurbineHeatSimulator.cs
using UnityEngine;
using System.Collections.Generic;
public class WindTurbineHeatSimulator : MonoBehaviour
{
[Header("热力图渲染组件")]
[SerializeField] private Heatmap heatmapComponent; // 引用您提供的Heatmap脚本
[Header("模拟参数")]
[SerializeField] private float ambientTemperature = 25f;
[SerializeField] private float simulationSpeed = 1.0f;
[SerializeField] private bool realTimeUpdate = true;
[Header("热点配置")]
[SerializeField] private List<SimulatedHotspot> hotspots = new List<SimulatedHotspot>();
[System.Serializable]
public class SimulatedHotspot
{
public string name = "热点";
public Transform centerTransform; // 热点中心的变换组件(可选)
public Vector3 localOffset; // 相对于模型局部坐标系的偏移
public float baseRadius = 1.0f;
public float baseIntensity = 1.0f;
public float fluctuationSpeed = 1.0f; // 波动速度
[Range(0f, 1f)] public float fluctuationAmount = 0.2f; // 波动幅度
[HideInInspector] public float phase; // 用于波动的相位
}
private float simulationTime = 0f;
private List<HeatPoint> currentHeatPoints = new List<HeatPoint>();
[Header("性能优化")]
[Tooltip("热力图数据更新的频率(秒)。降低频率可大幅提升性能。")]
[SerializeField] private float updateInterval = 0.1f; // 默认每秒更新10次而非每帧
[Tooltip("当热点数据未发生变化时,是否跳过本次更新提交。")]
[SerializeField] private bool updateOnlyOnChange = true;
private float updateTimer = 0f;
private List<HeatPoint> previousHeatPoints = new List<HeatPoint>(); // 用于比较数据是否变化
private void Start()
{
// 自动获取Heatmap组件
if (heatmapComponent == null)
{
heatmapComponent = GetComponent<Heatmap>();
}
if (heatmapComponent == null)
{
Debug.LogError($"在{gameObject.name}上未找到Heatmap组件。请确保已将Heatmap脚本附加到风机模型上。");
return;
}
// 如果没有配置热点,创建一些基于风机典型部位的默认热点
if (hotspots.Count == 0)
{
InitializeDefaultHotspots();
}
// 初始生成一次热力点
GenerateHeatPoints();
}
private void Update()
{
/*
if (!realTimeUpdate || heatmapComponent == null) return;
simulationTime += Time.deltaTime * simulationSpeed;
GenerateHeatPoints();*/
if (!realTimeUpdate || heatmapComponent == null) return;
// 1. 基于间隔时间的更新,而非每帧
updateTimer += Time.deltaTime;
if (updateTimer < updateInterval) return;
updateTimer = 0f;
// 2. 生成新的热力点数据
GenerateHeatPoints();
// 3. (可选)仅在数据发生变化时提交更新
if (updateOnlyOnChange && !HasHeatPointsChanged())
{
return; // 数据未变化跳过本次GPU提交
}
// 4. 提交数据到Heatmap组件
if (heatmapComponent != null && currentHeatPoints.Count > 0)
{
heatmapComponent.SetHeatPoints(currentHeatPoints);
UpdatePreviousHeatPoints(); // 记录当前数据用于下次比较
}
}
/// <summary>
/// 比较当前生成的热点数据与上一次是否相同
/// </summary>
private bool HasHeatPointsChanged()
{
if (previousHeatPoints.Count != currentHeatPoints.Count) return true;
for (int i = 0; i < currentHeatPoints.Count; i++)
{
// 简单比较位置、半径和强度。可以根据需要调整比较精度。
if (Vector3.Distance(previousHeatPoints[i].point, currentHeatPoints[i].point) > 0.001f ||
Mathf.Abs(previousHeatPoints[i].radius - currentHeatPoints[i].radius) > 0.001f ||
Mathf.Abs(previousHeatPoints[i].intensity - currentHeatPoints[i].intensity) > 0.001f)
{
return true;
}
}
return false;
}
private void UpdatePreviousHeatPoints()
{
previousHeatPoints.Clear();
// 进行深拷贝,而非引用拷贝
foreach (var point in currentHeatPoints)
{
previousHeatPoints.Add(new HeatPoint { point = point.point, radius = point.radius, intensity = point.intensity });
}
}
/// <summary>
/// 生成默认热点配置(基于典型风机结构)
/// </summary>
private void InitializeDefaultHotspots()
{
// 示例:创建三个代表发电机、齿轮箱和轴承的模拟热点
// 注意这些localOffset是示例值您需要根据风机模型的实际比例和轴心调整
hotspots.Add(new SimulatedHotspot
{
name = "发电机",
localOffset = new Vector3(0f, 0.8f, 0f), // 机舱上部
baseRadius = 1.5f,
baseIntensity = 1.2f,
fluctuationSpeed = 0.8f,
fluctuationAmount = 0.3f
});
hotspots.Add(new SimulatedHotspot
{
name = "齿轮箱",
localOffset = new Vector3(0.5f, 0.6f, 0f), // 机舱前部
baseRadius = 1.2f,
baseIntensity = 1.0f,
fluctuationSpeed = 1.2f,
fluctuationAmount = 0.25f
});
hotspots.Add(new SimulatedHotspot
{
name = "叶片根部轴承",
localOffset = new Vector3(0f, 1.0f, 1.5f), // 假设叶片沿Z轴伸出
baseRadius = 0.8f,
baseIntensity = 0.9f,
fluctuationSpeed = 2.0f, // 叶片旋转导致更快的波动
fluctuationAmount = 0.4f
});
}
/// <summary>
/// 核心方法:根据模拟参数生成热力点列表
/// </summary>
public void GenerateHeatPoints()
{
currentHeatPoints.Clear();
foreach (var config in hotspots)
{
// 计算热点在世界坐标系中的最终位置
Vector3 worldPosition = CalculateHotspotWorldPosition(config);
// 计算当前帧的强度和半径(加入波动模拟)
float currentIntensity = CalculateCurrentIntensity(config);
float currentRadius = CalculateCurrentRadius(config);
// 创建热力点数据结构
HeatPoint heatPoint = new HeatPoint
{
point = worldPosition,
radius = currentRadius,
intensity = currentIntensity
};
currentHeatPoints.Add(heatPoint);
}
// 将生成的热点数据提交给Heatmap组件进行渲染
if (heatmapComponent != null && currentHeatPoints.Count > 0)
{
heatmapComponent.SetHeatPoints(currentHeatPoints);
}
}
/// <summary>
/// 计算热点在世界空间中的位置
/// </summary>
private Vector3 CalculateHotspotWorldPosition(SimulatedHotspot config)
{
if (config.centerTransform != null)
{
// 如果指定了具体的Transform以其为基准
return config.centerTransform.position + config.centerTransform.TransformVector(config.localOffset);
}
else
{
// 否则,使用风机模型自身的变换,并加上局部偏移
return transform.position + transform.TransformVector(config.localOffset);
}
}
/// <summary>
/// 计算当前帧的热点强度(带波动)
/// </summary>
private float CalculateCurrentIntensity(SimulatedHotspot config)
{
// 基础强度 + 正弦波动
float fluctuation = Mathf.Sin(simulationTime * config.fluctuationSpeed + config.phase) * config.fluctuationAmount;
return config.baseIntensity * (1 + fluctuation);
}
/// <summary>
/// 计算当前帧的热点半径(可加入轻微波动,或保持恒定)
/// </summary>
private float CalculateCurrentRadius(SimulatedHotspot config)
{
// 此处示例半径保持恒定,您也可以加入波动
return config.baseRadius;
}
/// <summary>
/// 手动触发热力图更新(例如在检查器或由外部逻辑调用)
/// </summary>
[ContextMenu("手动更新热力图")]
public void ManualUpdateHeatmap()
{
GenerateHeatPoints();
}
/// <summary>
/// 添加一个运行时热点(可用于模拟故障)
/// </summary>
public void AddRuntimeHotspot(Vector3 worldPosition, float radius, float intensity, float duration = 5f)
{
// 创建一个临时热点配置
SimulatedHotspot tempHotspot = new SimulatedHotspot
{
name = "临时热点",
localOffset = transform.InverseTransformPoint(worldPosition), // 转换为局部坐标偏移
baseRadius = radius,
baseIntensity = intensity,
fluctuationSpeed = 3f,
fluctuationAmount = 0.5f
};
hotspots.Add(tempHotspot);
GenerateHeatPoints(); // 立即更新
// 可选:在指定时间后移除临时热点
if (duration > 0)
{
StartCoroutine(RemoveHotspotAfterDelay(tempHotspot, duration));
}
}
private System.Collections.IEnumerator RemoveHotspotAfterDelay(SimulatedHotspot hotspot, float delay)
{
yield return new WaitForSeconds(delay);
hotspots.Remove(hotspot);
GenerateHeatPoints();
}
/// <summary>
/// 在Scene视图中绘制Gizmos以可视化热点位置
/// </summary>
private void OnDrawGizmosSelected()
{
if (!Application.isPlaying)
{
// 在编辑模式下绘制配置的预设热点位置
Gizmos.color = Color.yellow;
foreach (var config in hotspots)
{
Vector3 pos = CalculateHotspotWorldPosition(config);
Gizmos.DrawWireSphere(pos, config.baseRadius * 0.5f); // 绘制小一些以便观察
Gizmos.DrawIcon(pos, "HeatmapIcon.png", true);
}
}
else
{
// 在运行模式下绘制当前实际的热力点
Gizmos.color = Color.red;
foreach (var hp in currentHeatPoints)
{
Gizmos.DrawWireSphere(hp.point, hp.radius * 0.3f);
}
}
}
}