39.性能优化-CPU-脚本-复杂计算结果缓存
39.1 知识点
复杂计算结果缓存
复杂计算结果缓存 指:避免对同一逻辑重复执行开销大的运算,把结果存起来复用,从而减少 CPU 运算量和时间。这类优化特别适合 频繁执行但输入变化不频繁 的逻辑。
常会缓存的计算结果
数学计算结果缓存
在初始化或加载阶段把常用数学结果提前算好。例如三角函数:用数组存 0~359 度对应的 Sin、Cos 等,运行时按角度下标查表,避免重复调用 Mathf.Sin / Mathf.Cos。
// 初始化时预计算 0~359 度的 Sin 值,运行时按角度索引取用
private float[] cachedSinValues;
void Start()
{
cachedSinValues = new float[360];
for (int degree = 0; degree < 360; degree++)
{
cachedSinValues[degree] = Mathf.Sin(degree * Mathf.Deg2Rad);
}
}
// 使用时直接查表,避免重复计算
float sinValue = cachedSinValues[angleDegree % 360];
同理可预计算 Cos、Tan 或其它常用数学表。
寻路计算结果缓存
若使用 A* 等寻路算法,可用容器(如 Dictionary)缓存「起点 + 终点」对应的路径。下次请求相同或等价的两点时,先查缓存,命中则直接返回路径,避免重复寻路。
静态配置数据缓存
配置表(如 Excel/JSON 反序列化后的数据)若被多处频繁使用,应在进入游戏或进入场景时一次性反序列化并常驻内存,后续逻辑直接读内存中的结构,避免每次用到都重新反序列化。
物理投射数据缓存
物理投射指用射线、球形/盒形 Overlap 等虚拟形状探测空间关系,常用于碰撞、视野、攻击判定。Unity 的 Raycast、OverlapSphere 等都属于这类 API。当位置、范围、相对关系不变且会多次复用时,可以把检测结果缓存下来,在条件未变时直接使用缓存,避免每帧重复检测。
Shader 参数缓存
应避免每帧重复设置相同的 Shader 属性,减少 CPU 到 GPU 的无效通信。在 C# 侧缓存当前已传入的值,仅在真正发生变化时再调用 material.SetFloat、SetVector 等传给着色器。
// 不推荐:每帧设置相同值
void Update()
{
material.SetFloat("_Speed", 5.0f);
}
// 推荐:缓存后仅在变化时设置
private float cachedSpeed = float.MinValue;
void Update()
{
float newSpeed = ComputeSpeed();
if (newSpeed != cachedSpeed)
{
cachedSpeed = newSpeed;
material.SetFloat("_Speed", cachedSpeed);
}
}
小结
若发现某些消耗高、结果可复用的复杂计算,都可以用「用内存换性能」的方式把结果缓存起来,避免重复计算。
39.2 知识点代码
Lesson39_性能优化_CPU_脚本_复杂计算结果缓存.cs
using UnityEngine;
public class Lesson39_性能优化_CPU_脚本_复杂计算结果缓存 : MonoBehaviour
{
// 0~359 度 Sin 值查表,避免运行时重复计算三角函数
private float[] cachedSinValues;
void Start()
{
#region 知识点一 复杂计算结果缓存
/* 将开销大的运算结果缓存复用,减少 CPU 与时间消耗;
* 适用于频繁执行但变化不频繁的逻辑。*/
#endregion
#region 知识点二 常会缓存的计算结果
/* 数学:预计算 Sin/Cos 等查表;寻路:缓存两点间路径;
* 配置:进游戏时反序列化常驻内存;物理:射线/Overlap 结果在条件不变时缓存;
* Shader:在 C# 中缓存参数,仅变化时再 SetFloat/SetVector 等。*/
cachedSinValues = new float[360];
for (int degree = 0; degree < 360; degree++)
{
cachedSinValues[degree] = Mathf.Sin(degree * Mathf.Deg2Rad);
}
#endregion
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com