Unity游戏基于身体部位的碰撞检测代码优化与可读性提升请求
优化Unity中基于身体部位碰撞检测的冗长Switch语句
核心优化思路
针对代码中重复逻辑多、switch冗长、可读性差的问题,从语义化枚举、字典映射消除switch、提取重复逻辑、替换硬编码字符串四个方向优化:
步骤1:用枚举替代整数类型的attackType
把无意义的整数换成有明确语义的枚举,大幅提升代码可读性:
// 定义攻击目标枚举,对应原attackType的整数值 public enum AttackTarget { None = -1, // 对应原-1 Unblockable = -2, // 对应原-2 Dodgeable = 0, // 对应原0 LegRight = 1, // 对应原1 ArmRight = 2, // 对应原2 HeadRight = 3, // 对应原3 LegLeft = 4, // 对应原4 ArmLeft = 5, // 对应原5 HeadLeft = 6 // 对应原6 } // 把原int attackType替换为枚举类型 public AttackTarget attackType;
步骤2:用字典映射格挡检查逻辑
将每个攻击类型对应的格挡判断逻辑存入字典,彻底消除重复的switch case:
private Dictionary<AttackTarget, Func<bool>> _blockChecks; // 在Awake或Start方法中初始化字典 private void Awake() { _blockChecks = new Dictionary<AttackTarget, Func<bool>>() { { AttackTarget.LegRight, () => swordSrc.isDefendingLegRight }, { AttackTarget.ArmRight, () => swordSrc.isDefendingArmRight }, { AttackTarget.HeadRight, () => swordSrc.isDefendingHeadRight }, { AttackTarget.LegLeft, () => swordSrc.isDefendingLegLeft }, { AttackTarget.ArmLeft, () => swordSrc.isDefendingArmLeft }, { AttackTarget.HeadLeft, () => swordSrc.isDefendingHeadLeft } }; }
步骤3:重构GetCollision方法,提取重复逻辑
把重复的掉血、格挡处理、闪避判断逻辑拆成独立方法,同时替换硬编码的name比较为更可靠的Tag:
// 提取重复的玩家掉血逻辑 private void DealPlayerDamage(int damage) { pim.PlayerDamage(damage); } // 处理可闪避攻击的专属逻辑 private void HandleDodgeableAttack() { if (!pa.playerIsDodging) { DealPlayerDamage(5); } else { pa.dodgeOnCooldown = false; pa.resetDodgeRoutine(); hitboxDisable(); } } // 处理格挡触发后的逻辑 private void HandleBlockedState() { if (weaponBlocked) { hitboxDisable(); RandomOpening(); ApplyForce(testvar1, testvar2); weaponBlocked = false; } } // 重构后的核心碰撞处理方法 public void GetCollision(Collision2D col) { // 处理AttackTarget.None的情况,提前返回减少嵌套 if (attackType == AttackTarget.None) { if (col.gameObject.CompareTag("Sword")) { hitboxDisable(); } else if (col.gameObject.CompareTag("Player")) { DealPlayerDamage(5); } return; } // 非玩家身体碰撞直接跳过 if (!col.gameObject.CompareTag("Player_Body")) return; switch (attackType) { case AttackTarget.Unblockable: DealPlayerDamage(5); break; case AttackTarget.Dodgeable: HandleDodgeableAttack(); break; default: // 通过字典快速获取对应格挡判断逻辑 if (_blockChecks.TryGetValue(attackType, out var isBlocked)) { if (!isBlocked.Invoke()) { DealPlayerDamage(5); } else { weaponBlocked = true; } } break; } HandleBlockedState(); }
额外优化建议
- 替换字符串比较:不要用
gameObject.name判断,在Unity编辑器中给对应物体设置Tag(比如Player、Sword、Player_Body),用CompareTag()更可靠,避免物体改名导致逻辑失效。 - 提取常量:把固定伤害值
5定义为常量private const int AttackDamage = 5;,后续修改时只需改一处。 - 扩展性提升:新增攻击类型时,只需在枚举和字典中添加条目,无需修改核心逻辑,符合开闭原则。
内容的提问来源于stack exchange,提问作者ShrikeDev
相关产品推荐
相关产品推荐

