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

Unity开发:如何通过接口移除RunManager中的Switch分支?

移除RunManager中SkorAdd方法的Switch分支方案

针对你遇到的问题,这里提供两种成熟的重构方案,彻底移除Switch分支同时保留原有UI逻辑:


方案1:面向多态的优雅实现(推荐)

利用接口扩展+多态特性,让每种硬币类型自己负责处理加分逻辑,符合开闭原则,新增硬币类型时无需修改RunManager代码。

步骤1:扩展ICoin接口,添加加分处理方法

public interface ICoin 
{
  string CoinName { get; set; }
  int Damage { get; set; }
  float MoveSpeed { get; set; }    
  // 新增:让硬币自身处理加分逻辑
  void AddScore(RunManager runManager);
}

步骤2:在具体硬币类中实现AddScore方法

以CopperCoin为例,其他硬币类型(SilverCoin/GoldCoin)同理实现:

[Serializable]
public class CopperCoin : MonoBehaviour, ICoin
{  
  string coinName;
  int damage ;
  float speed;

  RunManager runManager;
  
  public void Start()
  {
    runManager = FindAnyObjectByType<RunManager>();
    speed = runManager.coinMoveSpeed;
    
    var coinData = runManager.GetCoin(this.GetType().Name.ToString());
    coinName = coinData.CoinName;
    damage = coinData.Damage;
    this.tag = coinName;
  }

  // 实现接口方法,直接调用对应UI更新逻辑
  public void AddScore(RunManager runManager)
  {
    runManager.CopperCoinAdd(damage);
  }

  // 补全接口属性的get/set实现
  public string CoinName { get => coinName; set => coinName = value; }
  public int Damage { get => damage; set => damage = value; }
  public float MoveSpeed { get => speed; set => speed = value; }
}

步骤3:简化触发逻辑并废弃Switch分支

修改碰撞触发代码,直接让硬币自身处理:

public void OnTriggerEnter(Collider other)
{
  GameObject go = other.gameObject;
  if(go != null)
  {
    ICoin iCoin = go.GetComponent<ICoin>();
    if(iCoin != null)
    {
      iCoin.AddScore(manager);
    }
  }
}

此时RunManager中的SkorAdd方法可以直接删除,或保留为兼容旧调用的适配方法:

public void SkorAdd(ICoin coin)
{
  coin.AddScore(this);
}

方案2:委托字典映射(快速改造)

如果不想修改硬币类结构,可以通过字典将硬币名称与对应的加分方法绑定,替代Switch分支。

步骤1:在RunManager中初始化委托字典

using System;
using System.Collections.Generic;
using UnityEngine;

public class RunManager : MonoBehaviour
{
  // 定义加分方法的委托类型
  private delegate void ScoreAddHandler(int damage);
  // 字典:硬币名称 -> 对应加分方法
  private Dictionary<string, ScoreAddHandler> _scoreHandlers;

  private void Awake()
  {
    // 初始化字典,绑定所有硬币的加分逻辑
    _scoreHandlers = new Dictionary<string, ScoreAddHandler>()
    {
      {"CopperCoin", CopperCoinAdd},
      {"SilverCoin", SilverCoinAdd},
      {"GoldCoin", GoldCoinAdd}
    };
  }

  // 保留原有UI更新方法
  public void CopperCoinAdd(int damage)
  {
    // 原UI写入逻辑
  }

  public void SilverCoinAdd(int damage)
  {
    // 原UI写入逻辑
  }

  public void GoldCoinAdd(int damage)
  {
    // 原UI写入逻辑
  }

  // 修改SkorAdd方法,用字典查找替代Switch
  public void SkorAdd(string coinName, int damage)
  {
    if(_scoreHandlers.TryGetValue(coinName, out var handler))
    {
      handler(damage);
    }
    else
    {
      Debug.LogWarning($"未找到对应[{coinName}]的加分处理逻辑");
    }
  }
}

步骤2:触发逻辑无需修改

原碰撞触发代码可以继续使用,保持传递coinName和damage的逻辑即可。


额外优化建议

  1. 移除冗余的Coin类:现有Coin类仅存储名称和伤害,可直接用CoinDataSo替代,减少不必要的层级。
  2. 替换FindAnyObjectByType:在硬币类中通过Inspector拖拽赋值RunManager实例,避免运行时查找的性能损耗。
  3. 统一硬币命名规范:确保ScriptableObject的名称与硬币类名严格匹配,避免映射错误。

内容的提问来源于stack exchange,提问作者Gokhan Ozpay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:15:26