Unity自带寻路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gohuge/article/details/80244723
网格自动寻路:

①  把场景中不动的物体勾选static
②  烘焙寻路网格
③  给需要寻路的物体添加脚本添加NavMeshAgent组件和控制脚本

实现:
① 制作一个场景Terrain对象的地图,上面可以铺上一些Cube
把场景设为静态

径烘焙只烘焙静有静态导航属性的对象,也可以通过在Inspector中设置要烘焙的对象,没有改属性的变没有路径


烘焙过寻路网格后会显示蓝色的网格,表示可行走区域


选择window→navigation,调出navigation面板,选择bake,形成一个蓝色路面,enemy将在这个蓝色路面上进行寻路

注意,寻路对象的NavMeshAgent组件在没有网格的情况下不可使用。


using  System.Collections;  
using  System.Collections.Generic;  
using  UnityEngine;  
using  UnityEngine.AI;  
  
public   class  RayTest : MonoBehaviour {  
  
     private  Ray ray;  
     private  RaycastHit hit; //射线碰到的碰撞信息   
     public  GameObject navPlayer; //寻路的人   
     private  NavMeshAgent agent;  
  
     private   void  Start()  
    {  
        agent = navPlayer.GetComponent<NavMeshAgent>();  
    }  
  
     private   void  Update ()  
    {  
         //射线起始位置   
        ray = Camera.main.ScreenPointToRay(Input.mousePosition);  
         if (Physics.Raycast(ray, out  hit, 100) && Input.GetMouseButtonDown(0))  
        {  
            agent.SetDestination(hit.point);  
            Debug.DrawLine(ray.origin, hit.point, Color.red);  
        }  
    }  
}  

碰撞检测:

发生触发的条件:
1、发生碰撞的物体两者其中之一有Rigidbody即可,发生碰撞的两个游戏对象必须有Collider,其中一方勾选IsTrigger表示被动方 

2、确认地形上是可达的,像下图盒子放置的位置,恰好玩家卡在缝里上不去就一直没发生碰撞事件

角色控制

角色控制大概有4种途径,鼠标点击,键盘控制(下面代码附这两种逻辑),另外还有手机的重力感应和手势键盘

public class PlayerMove : MonoBehaviour
{
    
    [Header("是否点击移动")]
    public bool isClickMove = false;
    [Header("是否采用网格导航")]
    public bool IsNavAgent;
    [Header("移动速度")]
    public float m_speed = 5f;
    [Header("跑动动作")]
    public string RUN = "is_run";
    [Header("待机动作")]
    public string IDLE = "is_idle";


    float ogrY = 0;
    // 动作 0 待机,1 跑动
    int currentState = 0;


    // 寻路者  
    NavMeshAgent agent;
    // 玩家
    GameObject player;
    // 目标位置 
    Vector3 targetPos;


    void Start()
    {
        agent = this.GetComponent<NavMeshAgent>();
        targetPos = this.transform.position;
        ogrY = targetPos.y;
    }


    void LateUpdate()
    {
        if (isClickMove)
        {
            MoveControlByMouse();
        }
        else
        {
            MoveControlByTranslate();
        }
    }


    //Translate移动控制函数
    void MoveControlByTranslate()
    {
        if (Input.GetKey(KeyCode.W) | Input.GetKey(KeyCode.UpArrow)) //前
        {
            this.transform.Translate(Vector3.forward * m_speed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.S) | Input.GetKey(KeyCode.DownArrow)) //后
        {
            this.transform.Translate(Vector3.forward * -m_speed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.A) | Input.GetKey(KeyCode.LeftArrow)) //左
        {
            this.transform.Translate(Vector3.right * -m_speed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.D) | Input.GetKey(KeyCode.RightArrow)) //右
        {
            this.transform.Translate(Vector3.right * m_speed * Time.deltaTime);
        }
    }


    // 鼠标点击移动
    void MoveControlByMouse()
    {
        if (Input.GetMouseButton(0))
        {
            //获得鼠标屏幕位置  
            Vector3 mousePos = Input.mousePosition;
            //将屏幕位置转为射线  
            Ray ray = Camera.main.ScreenPointToRay(mousePos);
            //用来记录射线碰撞记录  
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                // 点中地板砖
                //if (!hit.collider.name.Equals("Terrain"))
                //{
                //    return;
                //}
                targetPos = new Vector3(hit.point.x, ogrY, hit.point.z);
                if (!player) {
                    player = this.transform.GetChild(0).gameObject;
                }
                // 差值 
                transform.rotation = Quaternion.LookRotation(targetPos - transform.position);
                if (IsNavAgent)
                {
                    agent.SetDestination(targetPos);
                }
                
            }
        }
        if (IsNavAgent)
        {
            if (agent.remainingDistance == 0)
            {
                AnimatorChange(0);
            }
            else
            {
                AnimatorChange(1);
            }
        }
        else {
            if (Mathf.Abs(transform.position.x - targetPos.x) > 0.1 || Mathf.Abs(transform.position.z - targetPos.z) > 0.1)
            {
                AnimatorChange(1);
                transform.position = Vector3.MoveTowards(transform.position, targetPos, m_speed * Time.deltaTime);
            }
            else
            {
                AnimatorChange(0);
            }
        }


    }


    // 动作切换
    void AnimatorChange(int state)
    {
        if (!player) return;
        if (currentState == state) return;
        currentState = state;
        switch (state)
        {
            case 0:
                Animator ani = player.GetComponent<Animator>();
                ani.SetTrigger(IDLE);
                break;
            case 1:
                ani = player.GetComponent<Animator>();
                ani.SetTrigger(RUN);
                break;
            default:
                break;
        }
    }
}

角色设置


猜你喜欢

转载自blog.csdn.net/gohuge/article/details/80244723