• 第39天A星寻路和路点寻路


    A星寻路

    Navigation

    1.渲染可寻路路径

    Navigation对需要渲染路径的模型勾选Navigation Static

    点击Bake 进行烘焙

    2.对需要进行寻路的物体添加Nav Mesh Agent 组件

    3.脚本

    需要引入using UnityEngine.AI;

    障碍物寻路

    需要将场景中的障碍物也勾选上navmesh Static 然后进行重新烘焙

    Bake参数

    Agent Radius:烘培路径可行与不可行的间隔

    Agent Height:可行的高度

    Max Slope:可行的最大坡度

    Step Height:最大台阶高度

    OffMeshLinks:

    • Drop Height:可行的最大跳下高度
    • Jump Distance:最大的跳跃距离

    Nav Mesh agent

    Bse Offest:组件的数值偏移

    Speed:移动速度

    Agular Speed:角速度

    Acceleration:加速度

    Stopping Distance:距离目标点多远停止

    Radius:寻路的碰撞半径

    Height:寻路的碰撞高度

    Quality:寻路的精细度

    Priority:寻路权重(0-99),值越小优先级越高,优先级地的寻路组件需要让着优先级高的走

    Auto Traverse Off  Mesh Link:是否支持Off 功能

    Auto Repath:自动重新规划路径

    Area Mask:可行路径区域

    API

    变量名.CalculatePath(Vector3 targetPosition,NavMeshPath path)  判断当前位置到目标位置的距离  计算到目标点的路径

    path.corners是当前路径中的拐点集合

    动态障碍

    Nav Mesh Obstacle组件

    注意勾选Carve

    路点寻路

    路点管理组件

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PathsManager : MonoBehaviour {
    
        List<EnemyGroup> enemyGroups = new List<EnemyGroup>();          //敌人分组列表
    
        public Transform[] nodes;                                       //路点组 本组件挂载在路点物体上
    
        private void Awake()
        {
            enemyGroups.Add(new EnemyGroup("Red", 5, 2, 5));            //添加一波Red敌人 ,5个 间隔2秒  下一组敌人到来时间
            enemyGroups.Add(new EnemyGroup("Green", 3, 1, 3));
            enemyGroups.Add(new EnemyGroup("Blue", 12, 1, 5));
    
            nodes = new Transform[transform.childCount];                //获取本物体下方的所有的子物体
            for (int i = 0; i < transform.childCount; i++)
            {
                nodes[i] = transform.GetChild(i);                       //给每个路点赋值
            }
        }
    
        private void Start()
        {
            StartCoroutine(StartCreateEnemy());                         //开启协程
        }
    
    
        IEnumerator StartCreateEnemy()
        {
            for (int i = 0; i < enemyGroups.Count; i++)                 //获取敌人一共有多少组
            {
                //i每一次循环控制一组一组敌人
    
                for (int j = 0; j < enemyGroups[i].num; j++)            //每一组敌人个数遍历
                {
                    //j每次循环控制当前组的敌人
                    CreateMonster(enemyGroups[i].prefabName);                   //生成敌人
                    yield return new WaitForSeconds(enemyGroups[i].interval);   //间隔几秒生成下一个
                }
    
                yield return new WaitForSeconds(enemyGroups[i].nextTime);       //间隔下一组敌人到来时间
            }
        }
    
    
        void CreateMonster(string prefabName)
        {
            GameObject prefab = Resources.Load<GameObject>(prefabName);         //根据传过来的敌人名,加载资源
            //克隆生成敌人
            GameObject monster = Instantiate(prefab, nodes[0].position, Quaternion.LookRotation(nodes[1].position - nodes[0].position));
    
            //设置路点
            monster.GetComponent<e>().SetPath(nodes);
        }
    
        //怪物组
        public struct EnemyGroup
        {
            public string prefabName;                                   //预制体名
            public int num;                                             //敌人数量
            public float interval;                                      //每个敌人生成间隔时间
            public float nextTime;                                      //下一组敌人间隔
    
            public EnemyGroup(string prefabName, int num, float interval, float nextTime)
            {
                this.prefabName = prefabName;
                this.num = num;
                this.nextTime = nextTime;
                this.interval = interval;
            }
        }
    }

    敌人组件

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        public float moveSpeed = 2f;
    
        public Queue<Transform> paths = new Queue<Transform>();
    
        private Transform target;
    
        void Update ()
        {
            if (Vector3.Distance(transform.position, target.position) <= moveSpeed * Time.deltaTime)        //判断距离目标点的距离是否小于下一次移动距离
            {
                transform.position = target.position;                                                       //到达目标距离
                if (paths.Count <= 0)                                                                       //判断路点数组是否还有数据
                {
                    //走到头了
                    Destroy(gameObject);                                                                    //如果没有说明到达终点,删除自己
                    return;
                }
                //要切换下一个路点
                target = paths.Dequeue();                                                                   //如果还有数据,则弹出下个目标点
                transform.LookAt(target);                                                                   //看向目标
            }
            else
            {
                transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);                          //向目标移动
            }
        }
        //给怪物设置路点
        public void SetPath(Transform[] nodes)
        {
            //将数组中的路点存储到队列中
            paths.Clear();                                                                                  //先清空数组
            for (int i = 0; i < nodes.Length; i++)
            {
                paths.Enqueue(nodes[i]);                                                                    //把路点一个一个存入数组
            }
    
            target = paths.Dequeue();                                                                       //弹出第一个路点
            transform.LookAt(target);                                                                       //朝向路点
        }
    
    }

    单波敌人逻辑

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MonsterManger : MonoBehaviour
    {
    
        public float interval = 2f;                             //每个怪物生成间隔
        public int monsterNum = 10;                             //怪物生成数量
    
        private float timer = 0f;                               //计时器
    
        public Transform[] nodes;                               //路点组
    
        private void Awake()
        {
            nodes = new Transform[transform.childCount];        //实例路点组对象,给出数组长度
            for (int i = 0; i < transform.childCount; i++)      //把每个路点赋值给路点数组
            {
                nodes[i] = transform.GetChild(i);
            }
        }
    
        // Update is called once per frame
        void Update ()
        {
            timer += Time.deltaTime;                            //计算时间
            if (timer >= interval && monsterNum > 0)            //如果计时器大于怪物生成间隔,且怪物总数大于0,则生成怪物
            {
                //生成怪物
                CreateMonster();
            }
        }
    
        void CreateMonster()
        {
            GameObject prefab = Resources.Load<GameObject>("Cube");     //加载怪物资源
            //克隆生成怪物
            GameObject monster = Instantiate(prefab, nodes[0].position, Quaternion.LookRotation(nodes[1].position - nodes[0].position));
    
            //把路点数组信息传给怪物
            monster.GetComponent<Enemy>().SetPath(nodes);
            timer = 0;                                                  //重新计时
            monsterNum--;                                               //怪物总数减1
        }
    
    
    
    }
  • 相关阅读:
    算法问题实战策略 题解
    算法杂题题解 合集
    算法问题实战策略 ASYMTILING
    Leetcode 139. 单词拆分 dp
    算法问题实战策略 FESTIVAL 摇滚音乐节
    PAT 甲级题解
    《挑战程序设计竞赛1》题解合集
    (七)React Ant Design Pro + .Net5 WebApi:后端环境搭建日志、异常处理
    nginx 超时
    (九)React Ant Design Pro + .Net5 WebApi:后端环境搭建IdentityServer4(一)简单配置
  • 原文地址:https://www.cnblogs.com/yifengs/p/14247557.html
Copyright © 2020-2023  润新知