Unity中FixedUpdate过多else if导致帧率下降的优化咨询
嘿,我完全懂你现在的头疼事儿——40个else if堆在FixedUpdate里,不仅帧率掉得厉害,以后要加新状态或者改参数时,简直是给自己挖了个维护大坑!咱们来把这堆逻辑重构得既高效又好维护,给你几个实用的方案:
方案1:枚举+配置数组(最直观,新手友好)
这是最容易上手的方案,把所有相机状态先定义成枚举,然后用一个数组存每个状态对应的offset参数,不用一堆判断,直接根据当前状态取配置就行。
步骤1:定义状态枚举和配置结构体
先在脚本里加个枚举,对应你原来的manjat、manjat2这些状态:
// 定义相机状态枚举 private enum CameraState { Normal, // 默认状态 Manjat, Manjat2, Manjat4, Manjat5 // 其他40个状态依次加在这里 } // 定义状态对应的配置结构体 [System.Serializable] private struct CameraOffsetConfig { public CameraState state; public Vector3 offset; }
步骤2:在Inspector里配置参数
在脚本里加一个可序列化的数组,这样你直接在Unity编辑器里就能拖放配置,不用改代码:
public CameraOffsetConfig[] offsetConfigs; // 在Inspector里配置每个状态对应的offset private CameraState currentState; private Vector3 currentOffset; // 缓存当前offset,不用每次都查
步骤3:初始化+状态切换逻辑
在Awake或者Start里先把默认offset设好,然后不要在FixedUpdate里判断状态——而是在状态变化的时候(比如PisauScript.nonaktifkamera里的变量改变时)更新currentState和currentOffset:
private void Awake() { // 初始化默认offset currentOffset = offset; } // 写一个专门更新状态的方法,不要在FixedUpdate里做判断! public void UpdateCameraState() { // 这里替换成你原来的状态判断逻辑,但只在状态变化时执行 if (PisauScript.nonaktifkamera.manjat) { SetCameraState(CameraState.Manjat); } else if (PisauScript.nonaktifkamera.manjat2) { SetCameraState(CameraState.Manjat2); } // ...其他状态判断 else { SetCameraState(CameraState.Normal); } } // 真正设置状态的方法 private void SetCameraState(CameraState newState) { if (currentState == newState) return; // 状态没变化就直接返回,避免重复操作 currentState = newState; // 从配置数组里找对应的offset foreach (var config in offsetConfigs) { if (config.state == newState) { currentOffset = config.offset; break; } } }
步骤4:简化FixedUpdate
现在FixedUpdate里就不用一堆判断了,直接用缓存的currentOffset:
private void FixedUpdate() { Vector3 desiredPosition = target.position + currentOffset; Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed); transform.position = smoothedPosition; }
方案2:字典映射(查找速度更快)
如果状态特别多(40个),用数组遍历还是有点慢,那可以把配置数组转成字典,查找时间是O(1),更高效:
修改初始化和SetCameraState方法
private Dictionary<CameraState, Vector3> offsetDict; private void Awake() { currentOffset = offset; // 把配置数组转成字典 offsetDict = new Dictionary<CameraState, Vector3>(); foreach (var config in offsetConfigs) { offsetDict[config.state] = config.offset; } } private void SetCameraState(CameraState newState) { if (currentState == newState) return; currentState = newState; // 直接从字典取,比遍历数组快多了 if (offsetDict.TryGetValue(newState, out Vector3 newOffset)) { currentOffset = newOffset; } else { // 没有找到对应状态时用默认值 currentOffset = offset; } }
方案3:状态模式(适合未来有复杂逻辑扩展)
如果以后每个相机状态不止改offset,还要加其他逻辑(比如切换相机FOV、开启特效),那状态模式更合适,每个状态对应一个类,职责更清晰:
步骤1:定义状态接口
private interface ICameraState { Vector3 GetOffset(); // 可以加其他方法,比如void EnterState()、void UpdateState()等 }
步骤2:实现每个状态类
private class ManjatState : ICameraState { public Vector3 GetOffset() { return new Vector3(-5, 14, 6); } } private class Manjat2State : ICameraState { public Vector3 GetOffset() { return new Vector3(-14, 25.5f, 6); } } // 其他状态类依次实现...
步骤3:管理状态切换
private ICameraState currentState; private void Awake() { // 默认状态 currentState = new NormalState(); } public void UpdateCameraState() { if (PisauScript.nonaktifkamera.manjat) { currentState = new ManjatState(); } else if (PisauScript.nonaktifkamera.manjat2) { currentState = new Manjat2State(); } // ...其他状态切换 else { currentState = new NormalState(); } } private void FixedUpdate() { Vector3 desiredPosition = target.position + currentState.GetOffset(); Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed); transform.position = smoothedPosition; }
额外优化小技巧
- 不要在FixedUpdate里访问静态变量:把
PisauScript.nonaktifkamera缓存成一个局部变量,比如在Awake里private NonaktifKamera kameraRef = PisauScript.nonaktifkamera;,避免每次都查找静态变量。 - 状态变化才更新:不要每一帧都判断40个状态,而是在
PisauScript.nonaktifkamera里的变量变化时(比如用事件通知),再调用UpdateCameraState,这样FixedUpdate里完全没有判断逻辑,帧率提升更明显。
内容的提问来源于stack exchange,提问作者Kira Angelic
相关产品推荐
相关产品推荐

