【unity 实现温度图+热力图,显示形式–MeshRenderer或UGUI】
前言:总结unity使用MeshRenderer或者RawImage实现温度图和热力图的效果,源码链接地址在文章结尾处,免费开放。对你有帮助的话,给博主点赞收藏加关注,感谢支持。。。。。。
文章目录
前言
博主做之前搜索了好多网站,都没有详细教程和源码,东拼西凑,博主打算记录一下,为了方便自己学习,也为了和我一样的小伙伴。。。
一、温度图热力图原理
博主的理解:像素替换。温度值设置一个颜色范围,在某一个温度值范围内,当前像素替换成对应的温度值像素。
PS:在这里3D的面片使用的等比例计算,UI使用的1:1替换像素。
二、项目步骤
1.工程准备
unity创建工程,博主在这里就不多说了,博主用的版本是unity2021.3.23f1c1
2.maya创建一个面片,长宽高100×100×1
三.代码详细讲解(以UI案例详细讲解)
1. 热力图代码基类设置HeatMapBase
包含颜色、半径、热力图位置点、热力图图片分辨率、热力值。代码如下:
using System;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Heat Map", menuName = "Templet/HeatMapBase", order = 1)]
public class HeatMapBase : ScriptableObject
{
[Tooltip("半径")] public float DisRatio = 0.5f;
[Tooltip("分辨率")] public float Resolution = 256;
[Tooltip("热力图相关信息")] public List<HeatMapInfo> HeatMapInfos = new List<HeatMapInfo>();
[Serializable]
public sealed class HeatMapInfo
{
[Tooltip("热力值")] public float MaxAmount;
[Tooltip("颜色")] public Color Color;
}
}
颜色在Inspector里面自己设置。
2. 在画布中新建一个RawImage,用来更新热力图最终效果。在RawImage上添加要显示热力图的点dot,每个dot上挂载HeatMapData.cs脚本,脚本中包含热力点位置、热力值大小。如下图所示:
需要注意的是:1.画布大小保持跟热力图分辨率一样的大小,这样就不需要计算偏移差,3D里面有计算偏移差的方法如下图
2.rawiamge和热力点的锚点中心点设置位置,如下图
3.HeatMapData.cs代码,如下图
using UnityEngine;
public class HeatMapData : MonoBehaviour
{
private Vector3 pos;
[Range(0, 120)]
public int Amount;
public Vector3 Pos {
get {
return transform.position; } set {
pos = value; } }
}
3. 画出热力图,直接上代码HeatMapDemo.cs,代码中含注释
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HeatMapDemo : MonoBehaviour
{
public HeatMapBase heatMapBase;
public HeatMapData[] Targets;
public RawImage raw;
void Start()
{
HeatMapCreat(heatMapBase);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
HeatMapCreat(heatMapBase);
}
}
/// <summary>
/// 创建热力图
/// </summary>
/// <param name="heatMapBase"></param>
public void HeatMapCreat(HeatMapBase heatMapBase)
{
//----初始化热力点基础信息-----
List<HeatMapInfo> heatMapInfos = new List<HeatMapInfo>();
for (int i = 0; i < Targets.Length; i++)
{
Vector3 Pixel = Targets[i].Pos;
HeatMapInfo heatMapInfo = new HeatMapInfo();
heatMapInfo.Pixel = new Vector2(Pixel.x, Pixel.y);
heatMapInfo.Amount = Targets[i].Amount;
heatMapInfos.Add(heatMapInfo);
}
HeatMapBuild heatMapBuild = new HeatMapBuild( heatMapBase, heatMapInfos);
raw.texture = heatMapBuild.GetHeatMapTexture();
}
}
4. 热力图核心代码,直接上代码HeatMapBuild.cs,代码中含注释
using System.Collections.Generic;
using UnityEngine;
public class HeatMapInfo
{
Vector2 pixel;
int amount; //数量
public Vector2 Pixel
{
get => pixel;
set => pixel = value;
}
public int Amount
{
get => amount;
set => amount = value;
}
}
public class HeatMapBuild
{
Texture2D HeatMapTexture;
//Vector3 modelSize = new Vector3(100, 1, 100);
/// <summary>
/// 构造HeatMapBuild
/// </summary>
/// <param name="heatMapBase">热力图模板</param>
/// <param name="heatMapInfos">热力图数据</param>
public HeatMapBuild(HeatMapBase heatMapBase, List<HeatMapInfo> heatMapInfos)
{
HeatMapTexture = new Texture2D((int)heatMapBase.Resolution, (int)heatMapBase.Resolution);
CreatHeatMap(ref HeatMapTexture, heatMapInfos, heatMapBase, 1);
}
public Texture2D GetHeatMapTexture()
{
if (HeatMapTexture)
{
return HeatMapTexture;
}
else
{
return Texture2D.whiteTexture;
}
}
/// <summary>
/// 生成热力图texture
/// </summary>
/// <param name="texture">热力图底图</param>
/// <param name="heatMapInfos">热力点数据</param>
/// <param name="heatMapBase">热力图模板</param>
/// <param name="MapRatio">底图缩放比率,等比例是1</param>
void CreatHeatMap(ref Texture2D texture, List<HeatMapInfo> heatMapInfos, HeatMapBase heatMapBase,
float MapRatio)
{
//------初始化每个像素
List<Vector2> my_Pixels = new List<Vector2>();
List<float> my_Values = new List<float>();
for (int y = 0; y < texture.height; y++)
{
for (int x = 0; x < texture.width; x++)
{
Vector2 pixel = new Vector2(x, y);
my_Pixels.Add(pixel);
my_Values.Add(0);
}
}
int allLength = my_Pixels.Count; //所有像素点数量
int pointLength = heatMapInfos.Count; //热力图兴趣点点数量
int colorLength = heatMapBase.HeatMapInfos.Count; //色块等级
float my_Distance = 0;
float my_MaxDis = 0;
float value = 0;
for (int i = 0; i < pointLength; i++)
{
for (int a = 0; a < allLength; a++)
{
my_Distance = Vector2.Distance(heatMapInfos[i].Pixel * MapRatio, my_Pixels[a]);
my_MaxDis = heatMapBase.DisRatio * heatMapInfos[i].Amount;
if (my_Distance < my_MaxDis)
{
value = (1 - Mathf.Pow(my_Distance, 2) / Mathf.Pow(my_MaxDis, 2)) * heatMapInfos[i].Amount;
if (value > my_Values[a])
{
my_Values[a] = value;
}
}
}
}
float my_CurMaxAmount = 0;
float my_UpDiffValue = 0;
float offset = 0;
Color my_UpColor;
for (int i = 0; i < allLength; i++)
{
if (i <= heatMapBase.Resolution || i >= allLength - heatMapBase.Resolution ||
i % heatMapBase.Resolution == 0 || (i - 1) % heatMapBase.Resolution == 0)
{
texture.SetPixel((int)my_Pixels[i].x, (int)my_Pixels[i].y, Color.clear);
continue;
}
for (int j = 0; j < colorLength; j++)
{
my_CurMaxAmount = heatMapBase.HeatMapInfos[j].MaxAmount;
if (my_Values[i] >= my_CurMaxAmount)
{
Color my_CurColor = heatMapBase.HeatMapInfos[j].Color;
if (j != 0)
{
my_UpDiffValue = heatMapBase.HeatMapInfos[j - 1].MaxAmount - my_CurMaxAmount;
my_UpColor = heatMapBase.HeatMapInfos[j - 1].Color;
offset = (my_Values[i] - my_CurMaxAmount) / my_UpDiffValue;
texture.SetPixel((int)my_Pixels[i].x, (int)my_Pixels[i].y,
Color.Lerp(my_CurColor, my_UpColor, offset));
break;
}
else
{
texture.SetPixel((int)my_Pixels[i].x, (int)my_Pixels[i].y, my_CurColor);
break;
}
}
}
}
texture.Apply();
}
}
四、项目运行结果以及源码链接
UI效果图:
MeshRenderer效果图:
源码链接:
网盘链接https://pan.baidu.com/s/1RNbe7MRfc3tEE81g8JH2WQ 提取码: s8ym
链接: https://pan.baidu.com/s/1RNbe7MRfc3tEE81g8JH2WQ 提取码: s8ym
PS:若想修改热力图,修改颜色和半径大小即可。有更好办法的网友欢迎随时交流,请留言给博主,博主看到会回复,谢谢。。。。。。