请选择 进入手机版 | 继续访问电脑版

简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE português คนไทย

签名
叶凡
22GS

[技术干货] unity编程实践-士兵巡逻技术实现代码分享

[复制链接]

unity编程实践-士兵巡逻技术实现代码分享

发表于 2021-12-27 11:33:42 来自 技术干货 阅读模式 倒序浏览
791 0 查看全部
作业要求创建一个地图和若干巡逻兵(使用动画);
每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
巡逻兵在设定范围内感知到玩家,会自动追击玩家;
失去玩家目标后,继续巡逻;
计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;

游戏设计要求工厂模式生产巡逻兵
部署工作
建立预制体

建立游戏地图预制,玩家预制和巡逻兵预制。其中,巡逻兵需要添加两个Collider,一个是Capsule Collider,添加在预制体父节点上,用于检测巡逻兵与玩家的碰撞。另一个是Box Collider,添加在预制体的子节点上,用于检测玩家进入巡逻兵巡逻的范围,可以通过调整Size的大小来控制检测的范围

重要代码分析
巡逻兵创建-PatrolData
  1.   public class PatrolData : MonoBehaviour
  2.   {
  3.       public int sign;                      //标志巡逻兵在哪一块区域
  4.       public bool follow_player = false;    //是否跟随玩家
  5.       public int wall_sign = -1;            //当前玩家所在区域标志
  6.       public GameObject player;             //玩家游戏对象
  7.       public Vector3 start_position;        //当前巡逻兵初始位置     
  8.   }
复制代码


巡逻兵创建-PropFactory

利用工厂模式生产巡逻兵,用数组记录每个巡逻兵的位置,创建的9个巡逻兵的位置有规律,所以可以用循环初始化位置坐标。当游戏结束时候,巡逻兵跑的动作被停止,将巡逻兵的动画设置为初始状态。

  1.   using System.Collections;
  2.   using System.Collections.Generic;
  3.   using UnityEngine;

  4.   public class PropFactory : MonoBehaviour
  5.   {
  6.       private GameObject patrol = null;                              //巡逻兵
  7.       private List<GameObject> used = new List<GameObject>();        //正在被使用的巡逻兵
  8.       private Vector3[] vec = new Vector3[9];                        //保存每个巡逻兵的初始位置

  9.       public FirstSceneController sceneControler;                    //场景控制器

  10.       public List<GameObject> GetPatrols()
  11.       {
  12.           int[] pos_x = { -6, 4, 13 };
  13.           int[] pos_z = { -4, 6, -13 };
  14.           int index = 0;
  15.           for(int i=0;i < 3;i++)
  16.           {
  17.               for(int j=0;j < 3;j++)
  18.               {
  19.                   vec[index] = new Vector3(pos_x[i], 0, pos_z[j]);
  20.                   index++;
  21.               }
  22.           }
  23.           for(int i=0; i < 9; i++)
  24.           {
  25.               patrol = Instantiate(Resources.Load<GameObject>("Prefabs/Patrol"));
  26.               patrol.transform.position = vec[i];
  27.               patrol.GetComponent<PatrolData>().start_position = vec[i];
  28.               used.Add(patrol);
  29.           }   
  30.           return used;
  31.       }
  32.       
  33.       public void StopPatrol()
  34.       {
  35.           for (int i = 0; i < used.Count; i++)
  36.           {
  37.               used[i].gameObject.GetComponent<Animator>().SetBool("run", false);
  38.           }
  39.       }
  40.   }
复制代码

巡逻兵巡逻-GoPatrolAction

巡逻兵巡逻的动作,逻兵的巡逻轨迹为矩形,根据四个方向来选择要去到的目的地,当当前位置与目的地相差0.9f的时候,换一个方向继续巡逻;当发现附近存在玩家时,会调用回调函数,使得巡逻兵改为追踪状态,追踪玩家。

  1.   public class GoPatrolAction : SSAction
  2.   {
  3.       private enum Dirction { EAST, NORTH, WEST, SOUTH };
  4.       private float pos_x, pos_z;                 //移动前的初始x和z方向坐标
  5.       private float move_length;                  //移动的长度
  6.       private float move_speed = 1.2f;            //移动速度
  7.       private bool move_sign = true;              //是否到达目的地
  8.       private Dirction dirction = Dirction.EAST;  //移动的方向
  9.       private PatrolData data;                    //侦察兵的数据
  10.       

  11.       private GoPatrolAction() {}
  12.       public static GoPatrolAction GetSSAction(Vector3 location)
  13.       {
  14.           GoPatrolAction action = CreateInstance<GoPatrolAction>();
  15.           action.pos_x = location.x;
  16.           action.pos_z = location.z;
  17.           //设定移动矩形的边长
  18.           action.move_length = Random.Range(4, 7);
  19.           return action;
  20.       }
  21.       public override void Update()
  22.       {
  23.           if (data.alive == false){
  24.               this.destroy = true;
  25.           }
  26.           //防止碰撞发生后的旋转
  27.           if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)
  28.           {
  29.               transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);
  30.           }            
  31.           if (transform.position.y != 0)
  32.           {
  33.               transform.position = new Vector3(transform.position.x, 0, transform.position.z);
  34.           }
  35.           Gopatrol();
  36.           if (data.follow_player)
  37.           {
  38.               this.destroy = true;
  39.               this.callback.SSActionEvent(this,0,this.gameobject);
  40.           }
  41.       }
  42.       public override void Start()
  43.       {
  44.           this.gameobject.GetComponent<Animator>().SetBool("run", true);
  45.           data  = this.gameobject.GetComponent<PatrolData>();
  46.       }

  47.       void Gopatrol()
  48.       {
  49.           if (move_sign)
  50.           {
  51.               switch (dirction)
  52.               {
  53.                   case Dirction.EAST:
  54.                       pos_x -= move_length;
  55.                       break;
  56.                   case Dirction.NORTH:
  57.                       pos_z += move_length;
  58.                       break;
  59.                   case Dirction.WEST:
  60.                       pos_x += move_length;
  61.                       break;
  62.                   case Dirction.SOUTH:
  63.                       pos_z -= move_length;
  64.                       break;
  65.               }
  66.               move_sign = false;
  67.           }
  68.           this.transform.LookAt(new Vector3(pos_x, 0, pos_z));
  69.           float distance = Vector3.Distance(transform.position, new Vector3(pos_x, 0, pos_z));
  70.           if (distance > 0.9)
  71.           {
  72.               transform.position = Vector3.MoveTowards(this.transform.position, new Vector3(pos_x, 0, pos_z), move_speed * Time.deltaTime);
  73.           }
  74.           else
  75.           {
  76.               dirction = dirction + 1;
  77.               if(dirction > Dirction.SOUTH)
  78.               {
  79.                   dirction = Dirction.EAST;
  80.               }
  81.               move_sign = true;
  82.           }
  83.       }

  84.   }
复制代码

巡逻兵追踪-PatrolFollowAction

巡逻兵将目标位置定位为玩家位置,将会向着玩家位置移动,直到玩家逃离追踪范围。

  1. public class PatrolFollowAction : SSAction

  2.   {

  3.       private float speed = 2f;            //跟随玩家的速度

  4.       private GameObject player;           //玩家

  5.       private PatrolData data;             //侦查兵数据



  6.       private PatrolFollowAction() {}

  7.       public static PatrolFollowAction GetSSAction(GameObject player)

  8.       {

  9.           PatrolFollowAction action = CreateInstance<PatrolFollowAction>();

  10.           action.player = player;

  11.           return action;

  12.       }



  13.       public override void Update()

  14.       {

  15.           if (data.alive == false){

  16.               this.destroy = true;

  17.           }

  18.           if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)

  19.           {

  20.               transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);

  21.           }

  22.           if (transform.position.y != 0)

  23.           {

  24.               transform.position = new Vector3(transform.position.x, 0, transform.position.z);

  25.           }

  26.          

  27.           Follow();

  28.           if (!data.follow_player)

  29.           {

  30.               this.destroy = true;

  31.               this.callback.SSActionEvent(this,1,this.gameobject);

  32.           }

  33.       }

  34.       public override void Start()

  35.       {

  36.           data = this.gameobject.GetComponent<PatrolData>();

  37.       }

  38.       void Follow()

  39.       {

  40.           transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);

  41.           this.transform.LookAt(player.transform.position);

  42.       }

  43.   }
复制代码

巡逻兵追踪-PatrolFollowAction

巡逻兵将目标位置定位为玩家位置,将会向着玩家位置移动,直到玩家逃离追踪范围。

  1.   public class PatrolFollowAction : SSAction
  2.   {
  3.       private float speed = 2f;            //跟随玩家的速度
  4.       private GameObject player;           //玩家
  5.       private PatrolData data;             //侦查兵数据

  6.       private PatrolFollowAction() {}
  7.       public static PatrolFollowAction GetSSAction(GameObject player)
  8.       {
  9.           PatrolFollowAction action = CreateInstance<PatrolFollowAction>();
  10.           action.player = player;
  11.           return action;
  12.       }

  13.       public override void Update()
  14.       {
  15.           if (data.alive == false){
  16.               this.destroy = true;
  17.           }
  18.           if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)
  19.           {
  20.               transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);
  21.           }
  22.           if (transform.position.y != 0)
  23.           {
  24.               transform.position = new Vector3(transform.position.x, 0, transform.position.z);
  25.           }
  26.          
  27.           Follow();
  28.           if (!data.follow_player)
  29.           {
  30.               this.destroy = true;
  31.               this.callback.SSActionEvent(this,1,this.gameobject);
  32.           }
  33.       }
  34.       public override void Start()
  35.       {
  36.           data = this.gameobject.GetComponent<PatrolData>();
  37.       }
  38.       void Follow()
  39.       {
  40.           transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);
  41.           this.transform.LookAt(player.transform.position);
  42.       }
  43.   }
复制代码

动作管理类-SSActionManager

此类管理巡逻兵是巡逻状态还是追踪状态,巡逻动作结束条件是需要追捕玩家,使用此类来实现追捕动作。而当玩家离开追捕范围后,需要重新巡逻,也需要使用此类实现从初始的位置和方向继续巡逻。在游戏结束后,此类也负责摧毁所有动作,停止巡逻兵的移动。

  1.   public void SSActionEvent(SSAction source, int intParam = 0, GameObject objectParam = null)
  2.       {
  3.           if(intParam == 0)
  4.           {
  5.               //侦查兵跟随玩家
  6.               PatrolFollowAction follow = PatrolFollowAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().player);
  7.               this.RunAction(objectParam, follow, this);
  8.           }
  9.           else
  10.           {
  11.               //侦察兵按照初始位置开始继续巡逻
  12.               GoPatrolAction move = GoPatrolAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().start_position);
  13.               this.RunAction(objectParam, move, this);
  14.               //玩家逃脱
  15.               //Singleton<GameEventManager>.Instance.PlayerEscape();
  16.           }
  17.       }


  18.       public void DestroyAll()
  19.       {
  20.           foreach (KeyValuePair<int, SSAction> kv in actions)
  21.           {
  22.               SSAction ac = kv.Value;
  23.               ac.destroy = true;
  24.           }
  25.       }
复制代码




回复

使用道具 举报

游客~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|极客同行 ( 蜀ICP备17009389号-1 ) 川公网安备 51019002006459号

© 2013-2016 Comsenz Inc. Powered by Discuz! X3.4