Unity 责任链模式(实例详解)

文章目录

责任链模式(Chain of Responsibility)在Unity中可用于处理一系列可能的请求,通过创建一个对象链来传递这些请求,每个对象都有机会处理它。下面给出5个基于Unity环境下的责任链模式的代码示例:

示例1:游戏事件处理系统

csharp 复制代码
// 基础事件处理器接口
public interface IGameEventHandler
{
    void HandleEvent(GameEvent gameEvent);
    IGameEventHandler NextHandler { get; set; }
}

// 具体事件处理器类
public class PlayerMoveEventHandler : IGameEventHandler
{
    public IGameEventHandler NextHandler { get; set; }

    public void HandleEvent(GameEvent gameEvent)
    {
        if (gameEvent is MoveEvent moveEvent && moveEvent.Target is Player)
        {
            // 处理玩家移动事件
            Debug.Log("Player moved.");
            if (NextHandler != null) NextHandler.HandleEvent(gameEvent); // 如果有下一个处理器则继续传递
        }
    }
}

public class EnemyMoveEventHandler : IGameEventHandler
{
    public IGameEventHandler NextHandler { get; set; }

    public void HandleEvent(GameEvent gameEvent)
    {
        if (gameEvent is MoveEvent moveEvent && moveEvent.Target is Enemy)
        {
            // 处理敌人移动事件
            Debug.Log("Enemy moved.");
            if (NextHandler != null) NextHandler.HandleEvent(gameEvent); // 如果有下一个处理器则继续传递
        }
    }
}

// 构建和使用链
public class GameEventManager
{
    private IGameEventHandler _headHandler;

    public GameEventManager()
    {
        var playerMoveHandler = new PlayerMoveEventHandler();
        var enemyMoveHandler = new EnemyMoveEventHandler();
        playerMoveHandler.NextHandler = enemyMoveHandler;
        _headHandler = playerMoveHandler;
    }

    public void DispatchEvent(GameEvent gameEvent)
    {
        _headHandler.HandleEvent(gameEvent);
    }
}

// 游戏事件定义
public abstract class GameEvent { }
public class MoveEvent : GameEvent
{
    public GameObject Target { get; set; }
    // 其他相关属性...
}

// 使用示例
var manager = new GameEventManager();
var moveEvent = new MoveEvent() { Target = /* 某个游戏对象 */ };
manager.DispatchEvent(moveEvent);

示例2:UI消息处理链

csharp 复制代码
// UI消息处理器接口
public interface IMessageHandler
{
    bool CanHandleMessage(UIEvent message);
    void HandleMessage(UIEvent message);
    IMessageHandler NextHandler { get; set; }
}

// 具体消息处理器类
public class ButtonClickHandler : IMessageHandler
{
    public IMessageHandler NextHandler { get; set; }

    public bool CanHandleMessage(UIEvent message)
    {
        return message is ButtonClickEvent;
    }

    public void HandleMessage(UIEvent message)
    {
        if (message is ButtonClickEvent clickEvent)
        {
            Debug.Log($"Button clicked: {clickEvent.ButtonName}");
            if (NextHandler != null && !NextHandler.CanHandleMessage(message))
            {
                NextHandler.HandleMessage(message);
            }
        }
    }
}

public class TextInputHandler : IMessageHandler
{
    // 同样的结构,处理文本输入事件
    // ...
}

// 构建和使用链
public class UIManager
{
    private IMessageHandler _headHandler;

    public UIManager()
    {
        var buttonHandler = new ButtonClickHandler();
        var textInputHandler = new TextInputHandler();
        buttonHandler.NextHandler = textInputHandler;
        _headHandler = buttonHandler;
    }

    public void SendMessage(UIEvent message)
    {
        if (_headHandler.CanHandleMessage(message))
        {
            _headHandler.HandleMessage(message);
        }
        else
        {
            Debug.LogWarning("No handler for this message.");
        }
    }
}

// UI事件定义
public abstract class UIEvent {}
public class ButtonClickEvent : UIEvent
{
    public string ButtonName { get; set; }
}
public class TextInputEvent : UIEvent
{
    public string Text { get; set; }
    // ...
}

// 使用示例
var uiManager = new UIManager();
var clickEvent = new ButtonClickEvent() { ButtonName = "Start" };
uiManager.SendMessage(clickEvent);

示例3:游戏内物理碰撞响应链

csharp 复制代码
// 碰撞处理器接口
public interface ICollisionHandler
{
    bool ShouldHandleCollision(Collision collision);
    void OnCollisionEnter(Collision collision);
    ICollisionHandler NextHandler { get; set; }
}

// 具体碰撞处理器类
public class HealthPickupCollisionHandler : ICollisionHandler
{
    public ICollisionHandler NextHandler { get; set; }

    public bool ShouldHandleCollision(Collision collision)
    {
        return collision.gameObject.CompareTag("Player") && collision.gameObject.TryGetComponent(out HealthComponent health);
    }

    public void OnCollisionEnter(Collision collision)
    {
        if (ShouldHandleCollision(collision))
        {
            var health = collision.gameObject.GetComponent<HealthComponent>();
            health.Restore(10); // 恢复生命值
            if (NextHandler != null)
            {
                NextHandler.OnCollisionEnter(collision);
            }
        }
    }
}

public class ScorePickupCollisionHandler : ICollisionHandler
{
    // 类似地处理得分拾取事件
    // ...
}

// 构建和使用链
public class CollisionManager : MonoBehaviour
{
    public ICollisionHandler HeadHandler;

    void OnCollisionEnter(Collision collision)
    {
        HeadHandler?.OnCollisionEnter(collision);
    }
}

// 使用示例
public class GameManager : MonoBehaviour
{
    void Start()
    {
        var healthPickupHandler = new HealthPickupCollisionHandler();
        var scorePickupHandler = new ScorePickupCollisionHandler();
        healthPickupHandler.NextHandler = scorePickupHandler;
        
        GetComponent<CollisionManager>().HeadHandler = healthPickupHandler;
    }
}

示例4:AI决策链

csharp 复制代码
// AI决策器接口
public interface IAIDecisionMaker
{
    bool Decide(GameObject agent, List<WorldState> worldStates);
    IAIDecisionMaker NextDecisionMaker { get; set; }
}

// 具体决策器类
public class FleeFromDangerDecisionMaker : IAIDecisionMaker
{
    public IAIDecisionMaker NextDecisionMaker { get; set; }

    public bool Decide(GameObject agent, List<WorldState> worldStates)
    {
        var inDanger = worldStates.Any(s => s.IsDangerNearby);
        if (inDanger)
        {
            // 逃离危险逻辑
            Debug.Log($"{agent.name} flees from danger.");
            return true; // 已作出决定,不需后续决策器处理
        }
        else if (NextDecisionMaker != null)
        {
            return NextDecisionMaker.Decide(agent, worldStates);
        }
        return false;
    }
}

public class FindResourceDecisionMaker : IAIDecisionMaker
{
    // 寻找资源的逻辑
    // ...
}

// 构建和使用链
public class AIThinkingManager
{
    public IAIDecisionMaker DecisionChain;

    public void MakeDecision(GameObject agent, List<WorldState> worldStates)
    {
        if (DecisionChain.Decide(agent, worldStates))
        {
            // 执行相应的动作
        }
    }
}

// 使用示例
public class AIController : MonoBehaviour
{
    void Start()
    {
        var fleeDecisionMaker = new FleeFromDangerDecisionMaker();
        var findResourceDecisionMaker = new FindResourceDecisionMaker();
        fleeDecisionMaker.NextDecisionMaker = findResourceDecisionMaker;
        
        var aiThinkingManager = new AIThinkingManager();
        aiThinkingManager.DecisionChain = fleeDecisionMaker;
    }
}

// 世界状态定义
public class WorldState { ... }

示例5:场景切换责任链

csharp 复制代码
// 场景切换处理器接口
public interface ISceneTransitionHandler
{
    bool CanTransitionTo(Scene scene);
    void TransitionTo(Scene scene);
    ISceneTransitionHandler NextHandler { get; set; }
}

// 具体场景切换处理器类
public class LoadMainMenuTransitionHandler : ISceneTransitionHandler
{
    public ISceneTransitionHandler NextHandler { get; set; }

    public bool CanTransitionTo(Scene scene)
    {
        return scene.name == "MainMenu";
    }

    public void TransitionTo(Scene scene)
    {
        SceneManager.LoadScene(scene.name);
        if (NextHandler != null && !NextHandler.CanTransitionTo(scene))
        {
            NextHandler.TransitionTo(scene);
        }
    }
}

public class QuitApplicationTransitionHandler : ISceneTransitionHandler
{
    // 处理退出应用的逻辑
    // ...
}

// 构建和使用链
public class SceneTransitionManager
{
    private ISceneTransitionHandler _headHandler;

    public SceneTransitionManager(ISceneTransitionHandler firstHandler)
    {
        _headHandler = firstHandler;
    }

    public void TryTransitionTo(Scene scene)
    {
        _headHandler.TransitionTo(scene);
    }
}

// 使用示例
public class GameManager : MonoBehaviour
{
    void Start()
    {
        var mainMenuHandler = new LoadMainMenuTransitionHandler();
        var quitHandler = new QuitApplicationTransitionHandler();
        mainMenuHandler.NextHandler = quitHandler;

        var transitionManager = new SceneTransitionManager(mainMenuHandler);
        // 当需要切换到特定场景时调用
public void OnMainMenuButtonClicked()
{
    var mainMenuScene = SceneManager.GetSceneByName("MainMenu");
    transitionManager.TryTransitionTo(mainMenuScene);
}

public void OnQuitButtonClicked()
{
    var quitScene = new Scene { name = "Quit" }; // 假设有一个表示退出的场景
    transitionManager.TryTransitionTo(quitScene);
}

TryTransitionTo 方法

```csharp
public void OnMainMenuButtonClicked()
{
    var mainMenuScene = SceneManager.GetSceneByName("MainMenu");
    transitionManager.TryTransitionTo(mainMenuScene);
}

public void OnQuitButtonClicked()
{
    var quitScene = new Scene { name = "Quit" }; // 假设有一个表示退出的场景
    transitionManager.TryTransitionTo(quitScene);
}

示例6:输入命令处理链

csharp 复制代码
// 输入命令处理器接口
public interface ICommandHandler
{
    bool CanHandleCommand(string command);
    void HandleCommand(string command);
    ICommandHandler NextHandler { get; set; }
}

// 具体命令处理器类
public class MovePlayerCommandHandler : ICommandHandler
{
    public ICommandHandler NextHandler { get; set; }

    public bool CanHandleCommand(string command)
    {
        return command.StartsWith("move player ");
    }

    public void HandleCommand(string command)
    {
        var direction = command.Substring("move player ".Length);
        // 根据direction移动玩家
        Debug.Log($"Player moved to {direction}.");
        if (NextHandler != null && !NextHandler.CanHandleCommand(command))
        {
            NextHandler.HandleCommand(command);
        }
    }
}

public class OpenDoorCommandHandler : ICommandHandler
{
    // 处理打开门的命令逻辑
    // ...
}

// 构建和使用链
public class CommandDispatcher
{
    private ICommandHandler _headHandler;

    public CommandDispatcher(ICommandHandler firstHandler)
    {
        _headHandler = firstHandler;
    }

    public void DispatchCommand(string command)
    {
        _headHandler.HandleCommand(command);
    }
}

// 使用示例
public class GameInputController : MonoBehaviour
{
    private CommandDispatcher _dispatcher;

    void Start()
    {
        var movePlayerHandler = new MovePlayerCommandHandler();
        var openDoorHandler = new OpenDoorCommandHandler();
        movePlayerHandler.NextHandler = openDoorHandler;

        _dispatcher = new CommandDispatcher(movePlayerHandler);
    }

    public void OnUserInput(string command)
    {
        _dispatcher.DispatchCommand(command);
    }
}

// 使用示例
_gameInputController.OnUserInput("move player north"); // 移动玩家到北方
_gameInputController.OnUserInput("open door west"); // 打开西边的门

以上六个示例展示了责任链模式在Unity中的应用,通过构建一系列处理器对象并按照特定条件传递请求或事件,使得每个处理器都有机会执行相应的操作,并且可以根据需要灵活地添加、删除或修改链中的处理器。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)


​最后我们放松一下眼睛

相关推荐
可喜~可乐2 小时前
C# WPF开发
microsoft·c#·wpf
666和7776 小时前
C#的单元测试
开发语言·单元测试·c#
小码编匠7 小时前
WPF 星空效果:创建逼真的宇宙背景
后端·c#·.net
超龄魔法少女8 小时前
[Unity] ShaderGraph动态修改Keyword Enum,实现不同效果一键切换
unity·技术美术·shadergraph
蔗理苦9 小时前
2024-12-24 NO1. XR Interaction ToolKit 环境配置
unity·quest3·xr toolkit
花生糖@9 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
向宇it10 小时前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
虾球xz10 小时前
游戏引擎学习第55天
学习·游戏引擎
yngsqq10 小时前
一键打断线(根据相交点打断)——CAD c# 二次开发
windows·microsoft·c#
TENET信条11 小时前
day53 第十一章:图论part04
开发语言·c#·图论