智能巡逻兵(学习订阅者与发布者模式)
- 提交要求:
- 游戏设计要求:
- 创建一个地图和若干巡逻兵(使用动画);
- 每个巡逻兵走一个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
{