You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:39:44