unity 热力图学习

1.单纯使用CPU进行初步的思路学习

思路:使用rawimage充当热力图,rawimage位置定死,在rawimage对应的三维地面上创建两个transform,分别对应左下角与右上角,将需要进行热力图显示的设备框在这个范围内。然后,在代码中使用rawimage本身的宽高和三维对应点的x z 差值,计算出设备在rawimage上的对应点。将设备温度转换为对应颜色,将颜色赋值给前面算出来的像素点。

代码:

复制代码
using SpringGUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestHeatMap : MonoBehaviour
{
    public RawImage heatmap;

    public List<GameObject> equipment;

    public Transform statPos, endPos;

    private float rawimageWidth, rawimageHeight;

    private float realWidth, realHeight;

    public Color maxColor = Color.red;

    public Color minColor = Color.blue;

    public float maxValue = 60;

    public float minValue = 10;

    /// <summary>
    /// 颜色衰减范围
    /// </summary>
    public float radius = 10;

    public enum FalloffType
    {
        Linear,
        Quadratic,
        Gaussian
    }

    public FalloffType falloffType = FalloffType.Linear;

    private Texture2D tex;

    private Color[,] colorBuffer;

    private void Start()
    {
        rawimageWidth = heatmap.rectTransform.rect.width;

        rawimageHeight = heatmap.rectTransform.rect.height;

        realWidth = endPos.position.x - statPos.position.x;

        realHeight = endPos.position.z - statPos.position.z;

        tex = new Texture2D((int)rawimageWidth, (int)rawimageHeight);

        colorBuffer = new Color[(int)rawimageWidth, (int)rawimageHeight];

        Color[] pixels = new Color[(int)rawimageWidth * (int)rawimageHeight];

        for (int i = 0; i < rawimageWidth; i++)
        {
            for (int j = 0; j < rawimageHeight; j++)
            {
                colorBuffer[i, j] = Color.clear;
            }
        }

        // 2. 放置"热点" (只标记中心点,不画圆)
        List<Vector3> points = new List<Vector3>(); // 存储 (x, y, intensity)

        for (int i = 0; i < equipment.Count; i++)
        {
            Vector3 pos = equipment[i].transform.position;

            int x = (int)((pos.x - statPos.position.x) / realWidth * rawimageWidth);

            int y = (int)((pos.z - statPos.position.z) / realHeight * rawimageHeight);

            float intensity = float.Parse(equipment[i].name) / maxValue; // 归一化强度

            points.Add(new Vector3(x, y, intensity));
        }

        // 3. 卷积核(定义热量如何扩散)
        int blurRadius = 30; // 扩散范围(调大这个值!)
        float sigma = 15f;   // 扩散平滑度

        // 4. 遍历画布,计算每个像素受所有热点的影响
        for (int y = 0; y < rawimageHeight; y++)
        {
            for (int x = 0; x < rawimageWidth; x++)
            {
                float totalHeat = 0;
                foreach (var p in points)
                {
                    float dist = Vector2.Distance(new Vector2(x, y), new Vector2(p.x, p.y));
                    // 高斯权重
                    float weight = Mathf.Exp(-(dist * dist) / (2 * sigma * sigma));
                    totalHeat += p.z * weight;
                }
                // 根据总热量映射颜色
                pixels[y * (int)rawimageWidth + x] = Color.Lerp(minColor, maxColor, totalHeat);
            }
        }

        tex.SetPixels(pixels);
        tex.Apply();
        heatmap.texture = tex;
    }

    /// <summary>
    /// 绘制圆形衰减
    /// </summary>
    /// <param name="centerx"></param>
    /// <param name="centery"></param>
    /// <param name="baseColor"></param>
    void DrawCicularGradient(int centerx, int centery, Color baseColor)
    {
        int radiusInt = Mathf.CeilToInt(radius);

        for (int x = centerx - radiusInt; x <= centerx + radiusInt; x++)
        {
            for (int y = centery - radiusInt; y <= centery + radiusInt; y++)
            {
                if (x >= 0 && x < rawimageWidth && y >= 0 && y < rawimageHeight)
                {
                    float distance = Mathf.Sqrt(Mathf.Pow(x - centerx, 2) + Mathf.Pow(y - centery, 2));

                    if (distance <= radius)
                    {
                        float falloff = CalculateFalloff(distance);

                        Color pixelColor = baseColor * falloff;

                        colorBuffer[x, y] += pixelColor;

                        //限制颜色不超过1
                        colorBuffer[x, y].r = Mathf.Clamp01(colorBuffer[x, y].r);
                        colorBuffer[x, y].g = Mathf.Clamp01(colorBuffer[x, y].g);
                        colorBuffer[x, y].b = Mathf.Clamp01(colorBuffer[x, y].b);
                        colorBuffer[x, y].a = Mathf.Clamp01(colorBuffer[x, y].a);
                    }
                }
            }
        }
    }

    void ApplyColorBufferToTexture()
    {
        for (int x = 0; x < rawimageWidth; x++)
        {
            for (int y = 0; y < rawimageHeight; y++)
            {
                tex.SetPixel(x, y, colorBuffer[x, y]);
            }
        }

        tex.Apply();
    }

    /// <summary>
    /// 计算衰减因子
    /// </summary>
    float CalculateFalloff(float normalizedDistance)
    {
        switch (falloffType)
        {
            case FalloffType.Linear:
                return 1 - normalizedDistance;
            case FalloffType.Quadratic:
                return 1 - normalizedDistance * normalizedDistance;
            case FalloffType.Gaussian:
                // 高斯衰减:e^(-距离² × 5)
                return Mathf.Exp(-normalizedDistance * normalizedDistance * 5);
            default:
                return 1f - normalizedDistance;
        }
    }
}

代码运行效果:

相关推荐
xian_wwq7 小时前
【学习笔记】模型权重管理:Safetensors与私有化Hub(23/35)
笔记·学习
其实防守也摸鱼7 小时前
运维--学习阶段问题解答(1)(自测)
linux·运维·服务器·数据库·学习·自动化·命令模式
ctrl_v助手7 小时前
Halcon学习笔记2
人工智能·笔记·学习
YUS云生8 小时前
Python学习笔记·第31天:FastAPI入门——路由、路径参数、查询参数与请求体
笔记·python·学习
铅笔侠_小龙虾9 小时前
Rust 学习目录
开发语言·学习·rust
渣渣灰飞10 小时前
MySQL 系统学习 第五阶段:企业级 MySQL 实战开发 第二章:RBAC 权限系统设计
android·学习·mysql
六bring个六10 小时前
open Harmony中分布式软总线的学习任务清单
分布式·学习·c/c++·open harmony
精神底层11 小时前
AI 学习笔记:研究方法的演变
人工智能·笔记·学习
依然范特东11 小时前
RAG学习总结3--检索技术
笔记·学习
白帽小阳12 小时前
[特殊字符]【2026最新】零基础入门学网络安全(详细路线图),看这篇就够了!
学习·安全·web安全·网络安全·安全运营·学习路线·web渗透