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

news/2024/5/19 16:03:21 标签: unity, 责任链模式, c#, 游戏引擎

文章目录

      • 示例1:游戏事件处理系统
      • 示例2:UI消息处理链
      • 示例3:游戏内物理碰撞响应链
      • 示例4:AI决策链
      • 示例5:场景切换责任链
      • 示例6:输入命令处理链

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

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

// 基础事件处理器接口
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消息处理链

// 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:游戏内物理碰撞响应链

// 碰撞处理器接口
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决策链

// 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:场景切换责任链

// 场景切换处理器接口
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:输入命令处理链

// 输入命令处理器接口
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)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述


http://www.niftyadmin.cn/n/5348945.html

相关文章

Ubuntu(22.04):安装VNC

Ubuntu(20.04):安装VNC_ubuntu安装vnc-CSDN博客 Ubuntu20.04上安装VNC与Ubuntu22.04安装VNC略有不同,试了很久才终于成功。 1.在Ubuntu22.04的终端里安装tightvncserver sudo apt install tigervnc-standalone-server 2.在Ubuntu22.04的终端里安装gnome-panel sudo apt inst…

QT + opengl 环境搭建(glfw, glad),创建一个简单窗口

一.下载glfw&#xff0c;glad并编译 1.glfw个人理解就是对底层opengl的一些基本接口的封装&#xff0c;提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入。glfw的下载地址&#xff1a;Download | GLFW&#xff0c;下载完成后…

Neo4j 国内镜像下载与安装

Neo4j 5.x 简体中文版指南 社区版&#xff1a;https://neo4j.com/download-center/#community 链接地址&#xff08;Linux版&#xff09;&#xff1a;https://neo4j.com/artifact.php?nameneo4j-community-3.5.13-unix.tar.gz 链接地址&#xff08;Windows&#xff09;&#x…

快速搭建一个基于MVC架构的Spring Boot应用

提示&#xff1a;如果对 MVC 架构模式不熟悉可以看我的博客 > MVC架构模式与三层架构 快速搭建一个基于MVC架构的Spring Boot应用 一、Web 服务二、快速构建一个Spring Web MVC的 Web 应用1.使用脚手架快速的搭建环境&#xff1a;2.准备数据库&#xff1a;3.编写Dao层访问数…

Unity 解释器模式(实例详解)

文章目录 示例1&#xff1a;基础解释器结构示例2&#xff1a;小于表达式&#xff08;LessThanExpression&#xff09;示例3&#xff1a;逻辑或表达式&#xff08;OrExpression&#xff09;示例4&#xff1a;逻辑非表达式&#xff08;NotExpression&#xff09;示例5&#xff1a…

关于SQLite 的下载与使用。配合python

win系统下&#xff1a; SQLite Download Page Precompiled Binaries for Windows sqlite-tools-win-x64-3450000.zip (4.77 MiB) 解压后&#xff0c;找个位置。然后设置环境变量指定位置。 可以手动建立.db文件。 也可以通过代码建立&#xff1a; 如下代码就是建立一个db文件。…

Ubuntu 下进行系统备份与迁移

经常一个项目做到一半&#xff0c;结果系统崩溃了&#xff0c;每次都得重装系统&#xff0c;因此&#xff0c;就在想怎么才能够直接在ubuntu系统备份现有的系统呢?找了很多教程&#xff0c;发现都需要安装软件&#xff0c;这些方法都比较复杂&#xff0c;后来终于找到一种简单…

Docker Registry(镜像仓库)

什么是Docker Registry 镜像仓库负责存储&#xff0c;管理和分发镜像&#xff0c;并且提供登入认证能力&#xff0c;建立仓库的索引。镜像仓库管理多个repositoy&#xff0c;repositoy通过命名来区分。每个repository包含一个或多个镜像&#xff0c;镜像通过镜像名称和标签&am…