Unity3d入门之路-订阅者与发布者模式

智能巡逻兵(学习订阅者与发布者模式)

  • 提交要求:
  • 游戏设计要求:
    • 创建一个地图和若干巡逻兵(使用动画);
    • 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
    • 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
    • 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
    • 失去玩家目标后,继续巡逻;
    • 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
  • 程序设计要求:
    • 必须使用订阅与发布模式传消息
      • subject:OnLostGoal
      • Publisher: ?
      • Subscriber: ?
    • 工厂模式生产巡逻兵
  • 友善提示1:生成 3~5个边的凸多边型
    • 随机生成矩形
    • 在矩形每个边上随机找点,可得到 3 - 4 的凸多边型
    • 5 ?
  • 友善提示2:参考以前博客,给出自己新玩法
简介

该游戏是一个逃离巡逻者的游戏,游戏通过控制方向键或WASD四个键来控制人物的上左下右。游戏有四个地区,每个地区都有一个zombie进行巡逻,玩家需要避开zombie,避开一次获得一分,被捕捉到则游戏结束。

完整代码:Github

UML图

在这里插入图片描述

实现过程

实际上,本次游戏设计使用的框架与之前的游戏都是类似的,本次游戏也使用到了一个新学习的设计模式——发布与订阅模式,主要用于处理事件。

订阅者与发布者模式:
订阅者与发布者模式主要用于处理一些事件,如本游戏中的碰撞事件,以及玩家逃脱追捕这些事件。而场景管理器就是这些事件发生的订阅者,而例如碰撞器等就是一些事件发布者,而我们定义一个EventManager来定义一些代理和订阅主题。

GameEventManager:定义了可订阅的主题(事件)。

public class GameEventManager : MonoBehaviour
{
    //分数变化
    public delegate void ScoreEvent();
    public static event ScoreEvent ScoreChange;
    //游戏结束变化
    public delegate void GameoverEvent();
    public static event GameoverEvent GameoverChange;

    //玩家逃脱
    public void Escape()
    {
        if (ScoreChange != null)
        {
            ScoreChange();  //玩家逃脱则加一分
        }
    }
    //玩家被捕
    public void Gameover()
    {
        if (GameoverChange != null)
        {
            GameoverChange();   //玩家被捕即游戏结束
        }
    }
}

事件发布:首先是碰撞事件,所以要为巡逻者添加碰撞器;然后玩家逃脱事件的发生在动作管理器中发布。

public class PlayerCollide : MonoBehaviour
{
    void OnCollisionEnter(Collision other)
    {
        //当玩家与巡逻兵相撞
        if (other.gameObject.tag == "Player")
        {
            //游戏结束,发布消息
            Singleton<GameEventManager>.Instance.Gameover();
        }
    }
}
//SSActionManager.cs

    ... 

    public void SSActionEvent(SSAction source, int intParam = 0, GameObject objectParam = null)
    {
        if (intParam == 0)
        {
            //侦查兵跟随玩家

            FollowAction follow = FollowAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().player);
            this.RunAction(objectParam, follow, this);
        }
        else
        {
            //侦察兵按照初始位置开始继续巡逻
            PatrolAction move = PatrolAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().startPosition);
            this.RunAction(objectParam, move, this);
            //玩家逃脱
            Singleton<GameEventManager>.Instance.Escape();
        }
    }

    ...

订阅者处理:场景管理器订阅了主题,在这里他将会给事件管理器一个为每个订阅主题事件处理函数。

//FirstController.cs

    ...

    //订阅者模式
    void OnEnable()
    {
        GameEventManager.ScoreChange += AddScore;
        GameEventManager.GameoverChange += Gameover;
    }



    void OnDisable()
    {
        GameEventManager.ScoreChange -= AddScore;
        GameEventManager.GameoverChange -= Gameover;
    }

    private void AddScore()
    {
        scoreRecorder.Add();
    }

    private void Gameover()
    {
        this.gameState = GameState.OVER;
        player.GetComponent<Animator>().enabled = false;
        for (int i = 0; i < patrols.Count; i++)
        {
            patrols[i].GetComponent<Animator>().enabled = false;
        }
        actionManager.DestroyAll();
    }

    ...

动作管理器:
SSAction:所有动作的父类。

public class SSAction : ScriptableObject            //动作
{

    public bool enable = true;                      //是否正在进行此动作
    public bool destroy = false;                    //是否需要被销毁

    public GameObject gameobject;                   //动作对象
    public Transform transform;                     //动作对象的transform
    public ISSActionCallback callback;              //回调函数

    protected SSAction() { }                        //保证SSAction不会被new

    //子类可以使用下面的函数
    public virtual void Start()                    
    {
        throw new System.NotImplementedException();
    }

    public virtual void Update()
    {
        throw new System.NotImplementedException();
    }

    public void Reset()
    {
        enable = false;
        destroy = false;
        gameobject = null;
        transform = null;
        callback = null;
    }
}

SSActionManager:动作管理器的具体实现,实现了巡逻者巡逻与追踪的动作切换。
public class SSActionManager : MonoBehaviour, ISSActionCallback
{

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
发布-订阅模式(Publish-Subscribe Pattern)具有以下特点和优势: 1. 解耦性:通过发布-订阅模式发布者订阅者之间的关系被解耦。发布者不需要知道谁是订阅者,订阅者也不需要知道谁是发布者。这种解耦性使得系统中的组件可以独立地进行修改、扩展和重用。 2. 异步通信:发布-订阅模式通常采用异步通信方式,即发布者订阅者之间不需要直接交互。这样可以提高系统的性能和响应速度,因为发布者不需要等待所有订阅者都处理完消息后才能继续执行。 3. 扩展性:发布-订阅模式支持动态添加和移除订阅者,以及新增主题和取消主题订阅的灵活性。这使得系统可以方便地进行扩展和改进,而不需要对已有的组件进行修改。 4. 消息传递机制:发布-订阅模式提供了一种灵活的消息传递机制。发布者可以将消息发送到指定的主题上,而订阅者可以选择订阅感兴趣的主题。这种机制使得系统中的不同组件可以通过消息进行通信,实现松耦合的架构。 5. 可靠性:发布-订阅模式可以提高系统的可靠性。当一个订阅者出现故障或无法处理消息时,不会影响其他订阅者的正常运行。系统可以容错地处理故障,确保消息的可靠传递。 6. 多对多通信:发布-订阅模式支持多对多的通信。一个发布者可以有多个订阅者,一个订阅者也可以订阅多个主题。这种多对多的通信方式能够满足复杂系统中不同组件之间的通信需求。 综上所述,发布-订阅模式具有解耦性、异步通信、扩展性、消息传递机制、可靠性和多对多通信等特点和优势,适用于需要实现解耦和异步通信的应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值