智能巡逻兵
游戏设计要求:
- 创建一个地图和若干巡逻兵(使用动画);
- 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
- 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
- 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
- 失去玩家目标后,继续巡逻;
- 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
程序设计要求:
巡逻兵动作
- 巡逻
每次获取巡逻动作时都会生成一个长度为4到7的随机距离,巡逻兵就会以这个距离的长方形轨迹巡逻。如果感知到了玩家在设定范围内,则巡逻动作被销毁,转为追踪动作。每Update一次,判断一次巡逻兵是否达到一个巡逻凸多边形的端点,若达到则改变方向,否则向目标点移动。
public static PatrolAction getSSAction(Vector3 location) {PatrolAction action = CreateInstance<PatrolAction>();action.posX = location.x;action.posZ = location.z;action.moveLength = UnityEngine.Random.Range(4, 7);return action;}public override void Start() {this.gameObject.GetComponent<Animator>().SetBool("run", true);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);}goPatrol();if(data.ifFollowPlayer && data.areaSign == data.sign) {this.destory = true;this.callback.SSActoinEvent(this, 0, this.gameObject);}}private void goPatrol() {if (isArrivedAnEndPoint) {switch (direction) {case Direction.EAST:posX -= moveLength;break;case Direction.NORTH:posZ += moveLength;break;case Direction.WEST:posX += moveLength;break;case Direction.SOUTH:posZ -= moveLength;break;}isArrivedAnEndPoint = false;}this.transform.LookAt(new Vector3(posX, 0, posZ));float distance = Vector3.Distance(transform.position, new Vector3(posX, 0, posZ));if(distance > 0.9) {transform.position = Vector3.MoveTowards(this.transform.position, new Vector3(posX, 0, posZ), speed * Time.deltaTime);}else {direction += 1;if(direction > Direction.SOUTH) {direction = Direction.EAST;}isArrivedAnEndPoint = true;}}
- 追踪
只要玩家进入巡逻兵设定的追踪范围,巡逻兵即追踪玩家,若追踪到玩家发生碰撞玩家即失败。若玩家脱离追踪范围,得分加一。
public static FollowAction getSSAction(GameObject player) {FollowAction action = CreateInstance<FollowAction>();action.player = player;return action;}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);}transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);this.transform.LookAt(player.transform.position);if (!data.ifFollowPlayer || data.areaSign != data.sign) {this.destory = true;this.callback.SSActoinEvent(this, 1, this.gameObject);}}
- 订阅与发布模式
发布/订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者),而是通过消息通道广播出去,让订阅改消息主题的订阅者消费到。
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 CrystalEvent();public static event CrystalEvent CrystalChange;public void playerEscape() {if(ScoreChange != null) {Debug.Log("Add score!");ScoreChange();}}public void gameOver() {if(GameOverChange != null) {GameOverChange();}}public void ReduceCrystalNum() {if(CrystalChange != null) {CrystalChange();}}
}
public class PatrolFactory : MonoBehaviour {private List<GameObject> usedPatrols = new List<GameObject>(); private Vector3[] vec = new Vector3[9];public List<GameObject> getPatrols() {int[] pos_x = { -6, 4, 13 };int[] pos_y = { -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_y[j]);index++;}}for(int i = 0; i < 9; i++) {GameObject 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];usedPatrols.Add(patrol);}return usedPatrols;}public void stopPatrol() {for(int i = 0; i < usedPatrols.Count; i++) {usedPatrols[i].gameObject.GetComponent<Animator>().SetBool("run", false);}}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!