UPL5-8——Transform 相关

避免运行时修改 Transform 父节点问题

在运行时修改 Transform​ 父节点(SetParent 方法)是一项开销较大的操作,主要原因:

  1. 会触发 Transform 的系统重建

    修改父节点会让 Unity 重建该物体及其子物体的层级关系和矩阵缓存
    会触发一系列递归更新,非常耗性能,尤其是在父物体或子物体很多的情况下

  2. 可能导致批处理中段

    如果对象原本属于同一个静态批处理,修改父节点后会导致重新分组甚至退出批处理

  3. 可能导致缓冲区拓展

    Transform 底层父子关系类似动态数组,修改父节点,可能导致缓冲区拓展,导致不必要内存分配

等等

避免运行时频繁修改 Transform 相关属性

频繁修改 Transform 属性,会牵一发动全身,可能引起连锁反应
特别是在存在大量物体的场景以及低端设备上,我们应该尽量避免这种情况的发生

  1. position​、rotation​、scale 的开销

    因为 Transform​ 组件中会存储与其父组件相关的数据
    因此直接修改 Transform​ 对象的 position​、rotation​、scale 等属性
    会导致内部进行大量未预料的矩阵乘法计算
    特别是对象在 Hierarchy 窗口中位置越深时,计算也就越多

    优化建议:
    使用 localPosition​、localRotation​、localScale 相关成本更小
    我们可以尽量使用这些本地属性值来修改其相关信息|

  2. 对其他组件的影响

    不断更改 Transform​ 组件属性会向其它相关组件发送内部通知
    比如:Collider​、Rigidbody​、Light​、Camera​ 等
    这些组件也必须进行相关处理,因为物理系统、渲染系统都需要知道 Transform​ 的新值才能进行相关更新
    因此我们要避免在一帧中多次对 Transform 相关属性进行修改

    优化建议:通过缓存的形式,尽量减少修改 Transform 属性的次数

避免运行时频繁使用 Transform 相关方法

  1. 避免滥用封装好的方法

    LookAt​、RotateAround 等方法内部可能存在额外计算,滥用会带来更多性能开销
    优化建议:自行计算旋转角度、看向等逻辑实现

  2. 避免频繁使用层级遍历相关方法

    transform.Find()​ 等查找方法,会在内部进行循环遍历,在复杂对象中非常消耗性能
    要尽量避免在 Update 等每帧执行方法中使用

    优化建议:在 Awake​ 或 Start 中初始化一次进行缓存