39.复杂计算结果缓存优化

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 的 RaycastOverlapSphere 等都属于这类 API。当位置、范围、相对关系不变且会多次复用时,可以把检测结果缓存下来,在条件未变时直接使用缓存,避免每帧重复检测。

Shader 参数缓存

应避免每帧重复设置相同的 Shader 属性,减少 CPU 到 GPU 的无效通信。在 C# 侧缓存当前已传入的值,仅在真正发生变化时再调用 material.SetFloatSetVector 等传给着色器。

// 不推荐:每帧设置相同值
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

×

喜欢就点赞,疼爱就打赏