赞
踩
使用的是2D模板,但是除了增加一个Z轴的考虑,其它基本都是一样的,当然如果你的3D场景是平坦面的话几乎代码可以直接复用。
想要让敌人沿着指定路线移动,就要规定他需要移动的路点位置。
在这里,我采用的是建立一个空对象line,在再这个line对象底下一次插入空对象point,使用空对象的原因是因为我们只需要路点得到的位置,除非特殊需求,我们不需要其它的组件属性,为了便于观察,设置点的图标,确定敌人是否会沿着点位移动。
接下来,关键就是如何取得这些点位的位置了,最开始我尝试使用GetComponentsInChildren<GameObject>();拿到所有的子物体,再取得所有子物体的TransForm获得位置,但是实际上这个方法不能直接拿子物体本身,所以<>中至二级选择取TransForm就可以了,之后的部分就非常简单了,见代码。
- //这个的理解难度相比于弹幕追踪要简单很多,实现难度也低很多,所以注释会比较少
- public class AI_Move_line : MonoBehaviour
- {
- public GameObject line;//线路组
-
- public Transform[] line_array;//所有路点位置的数组
-
- [Range(0, 50)]
- public float speed;//移动速度
-
- [Range(0, 2)]
- public int move_method;//移动循环方式
- //0为从出发点开始,到终点时从起点为目标再次开始循环移动
- //1为到了终点后,沿着原路返回,回到起始点后再次按路径到终点
- //2为到了终点后将不再移动
-
- private Rigidbody2D body;//刚体组件
-
- [Range(0, 10)]
- public float point_waittime;//每次到达一个位置后的的等待时间
-
- [Range(0, 10)]
- public float point_distance;//距离路点的位置容忍差
-
- private int index;//标点位置
-
- private bool set = true;//路径移动辅助,默认true
-
- void Start()
- {
- index = 0;
- body = GetComponent<Rigidbody2D>();
- line_array = line.GetComponentsInChildren<Transform>();//拿到所有的路点,确定寻路位置
- }
-
-
- void Update()//根据选择的移动方式进行移动
- {
- switch (move_method)
- {
- case 0:
- Move_line0();
- break;
- case 1:
- Move_line1();
- break;
- case 2:
- Move_line2();
- break;
- default:
- break;
- }
- }
-
- private float Get_Distance(Transform point)//获取物体和路点的距离
- {
- return Vector3.Distance(transform.position, point.position);
- }
-
- void Move_line0()//移动方式-0,这个判断格式使得此方法可以复用
- {
- if (Get_Distance(line_array[index]) <= point_distance && set)
- {
- index = (index + 1) % line_array.Length;
- }
- else if (Get_Distance(line_array[index]) <= point_distance && !set)
- {
- index--;
- }
- Move();
- }
-
- void Move_line1()//移动方式-1,到大最后一个点是修改set,使得line0中index从自增改为自减
- {
- if(index == line_array.Length - 1 && set)
- {
- set = false;
- }
- else if(index == 0 && !set)
- {
- set = true;
- }
- Move_line0();
- }
-
- void Move_line2()//判断到达终点后不再进行移动操作
- {
- if(index == line_array.Length -1 && Get_Distance(line_array[index]) <= point_distance)
- {
- return;
- }
- else
- {
- Move_line0();
- }
- }
-
- void Move()//朝向目标移动
- {
- Vector2 rot = line_array[index].position - transform.position;
- rot = rot.normalized;
- Vector2 position = transform.position;
- position.x += rot.x * speed * Time.deltaTime;
- position.y += rot.y * speed * Time.deltaTime;
- body.MovePosition(position);
- }
- }
line的作用就是存储路径,我们可以在编辑器界面设置好线路后,只需要将线路对象给line变量,就可以通过GetComponentsInChildren拿到所有子物体点的位置,特别要注意的一点是,这个方法还会将父物体本身的TransForm返回,如果你不想要计入这个点,可以将index起始设置为1。
另外这段代码其实很亢余,有些函数的调用判断其实可以简化的(Get_Distance)就是,所以仅做参考,实际使用需要学会简化算法的时间复杂度和空间复杂度,优化结构,节省性能开销。
再来看看我设置的三种方式移动效果
线路移动可以用于设置敌人沿着某个固定路线移动,从而产生一种巡逻的效果,当发现玩家时就退出线路移动追踪玩家,否则继续沿着路径移动。另外这些点在游戏中改变了位置时,敌人也会改变随之移动路径。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。