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

本文介绍了如何在Unity3d中使用订阅者与发布者模式设计智能巡逻兵游戏。游戏要求包括巡逻兵路径规划、碰撞检测和玩家追击等。通过工厂模式生产巡逻兵,使用GameEventManager处理事件,如碰撞和逃脱。SSActionManager负责动作管理,PatrolFactory实现巡逻兵的生成。文章还提到了游戏的不足和改进空间,强调了设计模式在复杂游戏功能中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  • 提交要求:
  • 游戏设计要求:
    • 创建一个地图和若干巡逻兵(使用动画);
    • 每个巡逻兵走一个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
{

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值