题目及要求
创建一个地图和若干巡逻兵(使用动画);
每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
巡逻兵在设定范围内感知到玩家,会自动追击玩家;
失去玩家目标后,继续巡逻;
计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
程序设计要求:
必须使用订阅与发布模式传消息
subject:OnLostGoal
Publisher: ?
Subscriber: ?
工厂模式生产巡逻兵
游戏规则
使用WSAD键上下左右移动player,先进入巡逻兵的视野内,巡逻兵进行追捕,逃脱后可获得一分,如果与巡逻兵碰撞则游戏失败。最后走到地图的门并走出地图后游戏胜利。
游戏UML类图
程序组件
程序使用了推荐博客中的预制以及场景,所以游戏界面大部分是相同的,不同的是内部的机制,订阅与发布模式以及游戏胜利的条件。感谢大佬提供参考。
巡逻兵
使用工厂模式创建巡逻兵,同时进行初始化巡逻兵的位置
public List<GameObject> GetPatrols()
{
int[] pos_x = { -6, 4, 13 };
int[] pos_z = { -4, 6, -13 };
int index = 0;
//生成不同的巡逻兵初始位置
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
vec[index] = new Vector3(pos_x[i], 0, pos_z[j]);
index++;
}
}
for (int i = 0; i < 9; i++)
{
patrol = Instantiate(Resources.Load<GameObject>("Prefabs/Patrol"));
patrol.transform.position = vec[i];
patrol.GetComponent<PatrolData>().sign = i + 1;
patrol.GetComponent<PatrolData>().start_position = vec[i];
used.Add(patrol);
}
return used;
}
订阅模式的使用,使用事件和delegate类进行接受发布者发布事件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameEventManager : MonoBehaviour
{
public delegate void ScoreEvent();
public static event ScoreEvent ScoreChange;
public delegate void GameoverEvent();
public static event GameoverEvent GameoverChange;
public delegate void PlayerWinGame();
public static event PlayerWinGame GameWin;
public void PlayerEscape()
{
if (ScoreChange != null)
{
ScoreChange();
}
}
public void PlayerGameover()
{
if (GameoverChange != null)
{
GameoverChange();
}
}
public void PlayerWin()
{
if (GameWin != null)
{
GameWin();
}
}
}
场景控制器中,进行发布事件和删除事件
void Gamewin()
{
Gameover();
game_win = true;
}
void AddScore()
{
recorder.AddScore();
}
void Gameover()
{
game_over = true;
patrol_factory.StopPatrol();
action_manager.DestroyAllAction();
}
void OnEnable()
{
GameEventManager.ScoreChange += AddScore;
GameEventManager.GameoverChange += Gameover;
GameEventManager.GameWin += Gamewin;
}
void OnDisable()
{
GameEventManager.ScoreChange -= AddScore;
GameEventManager.GameoverChange -= Gameover;
GameEventManager.GameWin -= Gamewin;
}
isWin.cs 具体实现GameWin事件的操作
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IsWin : MonoBehaviour
{
void iswin()
{
float a= this.gameObject.transform.position.z;
if (a <= -15f)
{
Singleton<GameEventManager>.Instance.PlayerWin();
}
}
void Update(){
iswin();
}
}
PlayerCollide.cs,实现玩家与巡逻兵碰撞后进行的事件,同时使游戏结束
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCollide : MonoBehaviour
{
void OnCollisionEnter(Collision other)
{
//当玩家与侦察兵相撞
if (other.gameObject.tag == "Player")
{
other.gameObject.GetComponent<Animator>().SetTrigger("death");
this.GetComponent<Animator>().SetTrigger("shoot");
Singleton<GameEventManager>.Instance.PlayerGameover();
}
}
}
分数记录,用来具体实现事件addSore的具体操作
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScoreRecorder : MonoBehaviour
{
public FirstSceneController sceneController;
public int score = 0; //分数
// Use this for initialization
void Start()
{
sceneController = (FirstSceneController)SSDirector.GetInstance().CurrentScenceController;
sceneController.recorder = this;
}
public int GetScore()
{
return score;
}
public void AddScore()
{
score++;
}
}
巡逻兵跟随玩家的具体实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolFollowAction : SSAction
{
private float speed = 2f;
private GameObject player;
private PatrolData data;
private PatrolFollowAction() { }
public override void Start()
{
data = this.gameobject.GetComponent<PatrolData>();
}
public override void Update()
{
if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)
{
transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);
}
if (transform.position.y != 0)
{
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
}
Follow();
if (!data.follow_player || data.wall_sign != data.sign)
{
this.destroy = true;
this.callback.SSActionEvent(this,1,this.gameobject);
}
}
public static PatrolFollowAction GetSSAction(GameObject player)
{
PatrolFollowAction action = CreateInstance<PatrolFollowAction>();
action.player = player;
return action;
}
void Follow()
{
transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);
this.transform.LookAt(player.transform.position);
}
}
巡逻兵动作管理
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolActionManager : SSActionManager
{
private GoPatrolAction go_patrol;
public void GoPatrol(GameObject patrol)
{
go_patrol = GoPatrolAction.GetSSAction(patrol.transform.position);
this.RunAction(patrol, go_patrol, this);
}
//停止所有动作
public void DestroyAllAction()
{
DestroyAll();
}
}
游戏演示视频
演示视频