作业要求创建一个地图和若干巡逻兵(使用动画);
每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
巡逻兵在设定范围内感知到玩家,会自动追击玩家;
失去玩家目标后,继续巡逻;
计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
游戏设计要求工厂模式生产巡逻兵
部署工作
建立预制体
建立游戏地图预制,玩家预制和巡逻兵预制。其中,巡逻兵需要添加两个Collider,一个是Capsule Collider,添加在预制体父节点上,用于检测巡逻兵与玩家的碰撞。另一个是Box Collider,添加在预制体的子节点上,用于检测玩家进入巡逻兵巡逻的范围,可以通过调整Size的大小来控制检测的范围
重要代码分析
巡逻兵创建-PatrolData
- public class PatrolData : MonoBehaviour
- {
- public int sign; //标志巡逻兵在哪一块区域
- public bool follow_player = false; //是否跟随玩家
- public int wall_sign = -1; //当前玩家所在区域标志
- public GameObject player; //玩家游戏对象
- public Vector3 start_position; //当前巡逻兵初始位置
- }
复制代码
巡逻兵创建-PropFactory 利用工厂模式生产巡逻兵,用数组记录每个巡逻兵的位置,创建的9个巡逻兵的位置有规律,所以可以用循环初始化位置坐标。当游戏结束时候,巡逻兵跑的动作被停止,将巡逻兵的动画设置为初始状态。 - using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class PropFactory : MonoBehaviour
- {
- private GameObject patrol = null; //巡逻兵
- private List<GameObject> used = new List<GameObject>(); //正在被使用的巡逻兵
- private Vector3[] vec = new Vector3[9]; //保存每个巡逻兵的初始位置
- public FirstSceneController sceneControler; //场景控制器
- 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>().start_position = vec[i];
- used.Add(patrol);
- }
- return used;
- }
-
- public void StopPatrol()
- {
- for (int i = 0; i < used.Count; i++)
- {
- used[i].gameObject.GetComponent<Animator>().SetBool("run", false);
- }
- }
- }
复制代码巡逻兵巡逻-GoPatrolAction 巡逻兵巡逻的动作,逻兵的巡逻轨迹为矩形,根据四个方向来选择要去到的目的地,当当前位置与目的地相差0.9f的时候,换一个方向继续巡逻;当发现附近存在玩家时,会调用回调函数,使得巡逻兵改为追踪状态,追踪玩家。 - public class GoPatrolAction : SSAction
- {
- private enum Dirction { EAST, NORTH, WEST, SOUTH };
- private float pos_x, pos_z; //移动前的初始x和z方向坐标
- private float move_length; //移动的长度
- private float move_speed = 1.2f; //移动速度
- private bool move_sign = true; //是否到达目的地
- private Dirction dirction = Dirction.EAST; //移动的方向
- private PatrolData data; //侦察兵的数据
-
- private GoPatrolAction() {}
- public static GoPatrolAction GetSSAction(Vector3 location)
- {
- GoPatrolAction action = CreateInstance<GoPatrolAction>();
- action.pos_x = location.x;
- action.pos_z = location.z;
- //设定移动矩形的边长
- action.move_length = Random.Range(4, 7);
- return action;
- }
- public override void Update()
- {
- if (data.alive == false){
- this.destroy = true;
- }
- //防止碰撞发生后的旋转
- 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.follow_player)
- {
- this.destroy = true;
- this.callback.SSActionEvent(this,0,this.gameobject);
- }
- }
- public override void Start()
- {
- this.gameobject.GetComponent<Animator>().SetBool("run", true);
- data = this.gameobject.GetComponent<PatrolData>();
- }
- void Gopatrol()
- {
- if (move_sign)
- {
- switch (dirction)
- {
- case Dirction.EAST:
- pos_x -= move_length;
- break;
- case Dirction.NORTH:
- pos_z += move_length;
- break;
- case Dirction.WEST:
- pos_x += move_length;
- break;
- case Dirction.SOUTH:
- pos_z -= move_length;
- break;
- }
- move_sign = false;
- }
- this.transform.LookAt(new Vector3(pos_x, 0, pos_z));
- float distance = Vector3.Distance(transform.position, new Vector3(pos_x, 0, pos_z));
- if (distance > 0.9)
- {
- transform.position = Vector3.MoveTowards(this.transform.position, new Vector3(pos_x, 0, pos_z), move_speed * Time.deltaTime);
- }
- else
- {
- dirction = dirction + 1;
- if(dirction > Dirction.SOUTH)
- {
- dirction = Dirction.EAST;
- }
- move_sign = true;
- }
- }
- }
复制代码巡逻兵追踪-PatrolFollowAction 巡逻兵将目标位置定位为玩家位置,将会向着玩家位置移动,直到玩家逃离追踪范围。 - public class PatrolFollowAction : SSAction
- {
- private float speed = 2f; //跟随玩家的速度
- private GameObject player; //玩家
- private PatrolData data; //侦查兵数据
- private PatrolFollowAction() {}
- public static PatrolFollowAction GetSSAction(GameObject player)
- {
- PatrolFollowAction action = CreateInstance<PatrolFollowAction>();
- action.player = player;
- return action;
- }
- public override void Update()
- {
- if (data.alive == false){
- this.destroy = true;
- }
- 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)
- {
- this.destroy = true;
- this.callback.SSActionEvent(this,1,this.gameobject);
- }
- }
- public override void Start()
- {
- data = this.gameobject.GetComponent<PatrolData>();
- }
- void Follow()
- {
- transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);
- this.transform.LookAt(player.transform.position);
- }
- }
复制代码巡逻兵追踪-PatrolFollowAction 巡逻兵将目标位置定位为玩家位置,将会向着玩家位置移动,直到玩家逃离追踪范围。 - public class PatrolFollowAction : SSAction
- {
- private float speed = 2f; //跟随玩家的速度
- private GameObject player; //玩家
- private PatrolData data; //侦查兵数据
- private PatrolFollowAction() {}
- public static PatrolFollowAction GetSSAction(GameObject player)
- {
- PatrolFollowAction action = CreateInstance<PatrolFollowAction>();
- action.player = player;
- return action;
- }
- public override void Update()
- {
- if (data.alive == false){
- this.destroy = true;
- }
- 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)
- {
- this.destroy = true;
- this.callback.SSActionEvent(this,1,this.gameobject);
- }
- }
- public override void Start()
- {
- data = this.gameobject.GetComponent<PatrolData>();
- }
- void Follow()
- {
- transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);
- this.transform.LookAt(player.transform.position);
- }
- }
复制代码动作管理类-SSActionManager 此类管理巡逻兵是巡逻状态还是追踪状态,巡逻动作结束条件是需要追捕玩家,使用此类来实现追捕动作。而当玩家离开追捕范围后,需要重新巡逻,也需要使用此类实现从初始的位置和方向继续巡逻。在游戏结束后,此类也负责摧毁所有动作,停止巡逻兵的移动。 - public void SSActionEvent(SSAction source, int intParam = 0, GameObject objectParam = null)
- {
- if(intParam == 0)
- {
- //侦查兵跟随玩家
- PatrolFollowAction follow = PatrolFollowAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().player);
- this.RunAction(objectParam, follow, this);
- }
- else
- {
- //侦察兵按照初始位置开始继续巡逻
- GoPatrolAction move = GoPatrolAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().start_position);
- this.RunAction(objectParam, move, this);
- //玩家逃脱
- //Singleton<GameEventManager>.Instance.PlayerEscape();
- }
- }
- public void DestroyAll()
- {
- foreach (KeyValuePair<int, SSAction> kv in actions)
- {
- SSAction ac = kv.Value;
- ac.destroy = true;
- }
- }
复制代码
|