前言
在战斗场景打开Frame Debug窗口,发现场景中的血条绘制了100次,需要优化一下。
使用GPU Instancing的好处
- 极低的DrawCall数量
- 高效的GPU利用率
- 支持大量实例同时渲染
- 内存占用较低
- 更新性能优秀
项目
场景布置
创建一个空物体

创建脚本并挂载赋值
创建一个材质球
这里使用ASE创建一个简单的Shader意思一下


编写代码
using UnityEngine;
using System.Collections.Generic;
public class CreateHPBar : MonoBehaviour
{
public GameObject hpBarPrefab;
public Material sharedMaterial;
private MaterialPropertyBlock propertyBlock;
private List<MeshRenderer> renderers = new List<MeshRenderer>();
void Awake()
{
propertyBlock = new MaterialPropertyBlock();
}
void Start()
{
// 1. 首先创建所有实例并收集渲染器引用
for (int i = 0; i < 10; i++)
{
GameObject hpb = Instantiate(hpBarPrefab, new Vector3(i * 2, 0, 0), Quaternion.identity);
MeshRenderer render = hpb.GetComponent<MeshRenderer>();
render.sharedMaterial = sharedMaterial;
renderers.Add(render);
}
// 2. 一次性设置所有属性
UpdateAllHPBars();
}
// 统一更新所有血条的方法
private void UpdateAllHPBars()
{
propertyBlock.Clear(); // 清除之前的属性设置
// 为每个渲染器设置相同的PropertyBlock
for (int i = 0; i < renderers.Count; i++)
{
propertyBlock.Clear();
propertyBlock.SetFloat("_FakeHpValue", 0.1f * i);
renderers[i].SetPropertyBlock(propertyBlock);
}
}
// 如果需要动态更新某个血条
public void UpdateSingleHPBar(int index, float value)
{
if (index >= 0 && index < renderers.Count)
{
propertyBlock.Clear();
propertyBlock.SetFloat("_FakeHpValue", value);
renderers[index].SetPropertyBlock(propertyBlock);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
UpdateSingleHPBar(2, 1.0f);
}
if (Input.GetKeyDown(KeyCode.W))
{
UpdateSingleHPBar(2, 0.0f);
}
}
}
使用GPU Instancing优化血条渲染
此时运行场景能够看到这些血条并没有合批

需要设置修改的值为Instanced Property

并且勾选Per Renderer Data

确保Shader设置中勾选GPU Instancing

修改完成之后

总结
这种方案不适用于UGUI系统。
可以直接应用于此血条(需要修改Shader为URPUnLit)
Unity Shader分段式血条
4911

被折叠的 条评论
为什么被折叠?



