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的逻辑即可。
额外优化建议
- 移除冗余的Coin类:现有
Coin类仅存储名称和伤害,可直接用CoinDataSo替代,减少不必要的层级。 - 替换FindAnyObjectByType:在硬币类中通过Inspector拖拽赋值RunManager实例,避免运行时查找的性能损耗。
- 统一硬币命名规范:确保ScriptableObject的名称与硬币类名严格匹配,避免映射错误。
内容的提问来源于stack exchange,提问作者Gokhan Ozpay
相关产品推荐
相关产品推荐

