Unity C#类Minecraft项目区块边界立方体优化的冗余代码问题
区块立方体优化方法冗余消除方案
1. 抽离公共判断逻辑
先把“判断立方体是否被完全包围”的核心逻辑单独封装成独立方法,这是两个原方法共用的核心,抽离后彻底避免重复代码:
// 预定义六个方向向量,避免重复写硬编码值 private readonly Vector3[] _surroundingDirs = { Vector3.up, Vector3.down, Vector3.forward, Vector3.back, Vector3.right, Vector3.left }; // 公共判断方法:输入立方体位置和区块上下文,返回是否被完全包围 private bool IsCubeFullySurrounded(Vector3 cubePos, ChunkContext context) { foreach (var dir in _surroundingDirs) { // 替换成你原方法中检查对应方向是否有方块/区块的逻辑 if (!CheckBlockExists(cubePos + dir, context)) { return false; } } return true; }
2. 用回调分离差异行为
两个方法的核心差异在于判断后的动作:一个是跳过实例化,一个是禁用已存在的立方体。用委托(回调)把动作逻辑抽出来,写一个通用处理方法:
// 通用处理方法:传入判断所需参数,以及两种状态下的动作 private void ProcessCube(Vector3 cubePos, ChunkContext context, Action onSurrounded, Action onExposed = null) { bool isSurrounded = IsCubeFullySurrounded(cubePos, context); if (isSurrounded) { onSurrounded?.Invoke(); } else { onExposed?.Invoke(); } } // 处理新区块立方体:被包围则跳过实例化,否则创建 private void HandleNewChunkCube(Vector3 cubePos, ChunkContext context) { ProcessCube(cubePos, context, onSurrounded: () => { /* 空实现,直接跳过实例化 */ }, onExposed: () => { InstantiateCube(cubePos, context); } ); } // 处理邻接区块立方体:被包围则禁用,否则启用 private void HandleAdjacentChunkCube(GameObject cube, ChunkContext context) { Vector3 cubePos = cube.transform.position; ProcessCube(cubePos, context, onSurrounded: () => { cube.SetActive(false); }, onExposed: () => { cube.SetActive(true); } ); }
3. 泛型的合理使用场景
如果你的两个方法操作的对象类型不同(比如一个是预制体,一个是已实例化的Cube对象),可以用泛型约束统一方法签名,但泛型只解决类型重复问题,核心差异还是靠回调处理:
// 泛型版通用处理方法,约束对象为Unity的Object类型 private void ProcessCube<T>(T cubeObj, Vector3 cubePos, ChunkContext context, Action<T> onSurrounded, Action<T> onExposed = null) where T : UnityEngine.Object { bool isSurrounded = IsCubeFullySurrounded(cubePos, context); if (isSurrounded) { onSurrounded?.Invoke(cubeObj); } else { onExposed?.Invoke(cubeObj); } } // 调用示例:处理预制体 ProcessCube(cubePrefab, cubePos, context, onSurrounded: (_) => { /* 跳过实例化 */ }, onExposed: (prefab) => { Instantiate(prefab, cubePos, Quaternion.identity); } ); // 调用示例:处理已存在的立方体 ProcessCube(existingCube, cubePos, context, onSurrounded: (cube) => { cube.SetActive(false); }, onExposed: (cube) => { cube.SetActive(true); } );
4. 额外精简技巧
如果需要反向判断(比如检查是否未被包围),给IsCubeFullySurrounded加一个可选参数实现结果反转,避免重复写反向逻辑:
private bool IsCubeFullySurrounded(Vector3 cubePos, ChunkContext context, bool invertResult = false) { bool isSurrounded = true; foreach (var dir in _surroundingDirs) { if (!CheckBlockExists(cubePos + dir, context)) { isSurrounded = false; break; } } return invertResult ? !isSurrounded : isSurrounded; }
学习方向建议
- 重点掌握封装与抽象:学会拆分代码中的“可变部分”和“不变部分”,把不变逻辑封装,可变逻辑抽象成接口或委托。
- 理解策略模式:这是处理“同逻辑不同行为”场景的经典方案,用委托就能轻量实现,无需复杂框架。
- 泛型进阶:明确泛型的核心作用是解决类型重复问题,不要用泛型处理行为差异,行为差异交给回调或策略。
内容的提问来源于stack exchange,提问作者Oz4kk
相关产品推荐
相关产品推荐

