Unity使用NaveMesh实现第一人称视角移动

news2025/7/21 4:30:41

系列文章目录

Navemesh寻路系列文章


文章目录

目录

系列文章目录

文章目录

前言

一、NavMeshPath是什么?

二、使用步骤

1.引入库

2.读入数据

总结



前言

navemesh已经大量使用到游戏中,但大部分寻路都是使用SetDestination函数,给予一个目标点移动,第一人称直接操控移动的文章很少。

为了解决这个问题,特此出了这篇文章。


这篇博客主要使用NavMeshPath,通过得到移动数组,最终实现正确移动。

一、NavMeshPath是什么?

由导航系统计算的路径。

路径以路标列表的形式表示,存储在 corners 数组中。这些路标不是由用户脚本直接设置的,但 NavMesh.CalculatePath 函数和 NavMeshAgent.path 属性会返回分配有正确路标的 NavMeshPath。

corners路径的角点。(只读)
status路径状态。(只读)

二、使用步骤

1.引入库

代码如下:

using UnityEngine;
using UnityEngine.AI;

2.读入数据

代码如下(示例):

  NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);

该处可以获取到navemesh的寻路路径。

然后使用位移实现点到点之间的移动,目前的写法可以适用于上下坡等不平整地图。

完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;


/// <summary>
/// 人物平滑移动器
/// </summary>
public class AgentMove : MonoBehaviour
{

    public float speed = 0.5f;


    // Start is called before the first frame update
    void Start()
    {
        NavMeshAgent = transform.gameObject.GetComponent<NavMeshAgent>();
        m_NavMeshPath = new NavMeshPath();      
    }



    private NavMeshAgent NavMeshAgent;

    private NavMeshPath m_NavMeshPath;

    /// <summary>
    /// 前一个路径点索引
    /// </summary>
    private int m_previousIndex = 0;

    /// <summary>
    /// 后一个路径点索引
    /// </summary>
    private int m_currentIndex = 1;

    private bool isUpdate = false;

    void GetNav(Vector3 _pos)
    {
        isUpdate = true;
        Debug.LogError(transform.position + "  " + _pos);
        transform.LookAt(_pos);
        //计算NavMeshPath
        NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);
        //初始化路径点索引
        m_previousIndex = 0;
        m_currentIndex = 1;

        //if (m_NavMeshPath.corners.Length>1)
        //transform.position = m_NavMeshPath.corners[m_CurrentPathPointIndex];
        //Debug.Log(m_NavMeshPath.corners[m_CurrentPathPointIndex]+"  "+ m_NavMeshPath.corners.Length);

    }

    /// <summary>
    /// 移动到目标点(NavMeshPath.corners第0个路径点是当前游戏物体所在位置,以此类推)
    /// </summary>
    public void RunToTarget()
    {
        isUpdate = m_currentIndex <= m_NavMeshPath.corners.Length - 1;
        //防止数组越界
        if (!isUpdate) return;

        var _pos = transform.position;
        _pos.y = m_NavMeshPath.corners[m_currentIndex].y;
        //如果游戏物体坐标与当前路径点坐标距离小于0.1即可认为已抵达,可以向下一个路径点导航
        if ((_pos - m_NavMeshPath.corners[m_currentIndex]).magnitude <= 0.1f)
        {
            //递增路径点索引
            m_previousIndex++;
            m_currentIndex++;
            //防止数组越界
            if (m_currentIndex > m_NavMeshPath.corners.Length - 1)
            {
                //Debug.LogError(m_NavMeshPath.corners[m_CurrentPathPointIndex]);               
                //处理动画切换,请无视
                return;
            }

            //处理人物转向,请无视
        }

        //匀速运动。计算出前一个路径点到当前路径点方向,然后移动
        transform.Translate(
            ((-m_NavMeshPath.corners[m_previousIndex] +
              m_NavMeshPath.corners[m_currentIndex]).normalized) *
            (/*Time.deltaTime **/ speed/* *2f*/), Space.World);

        Debug.Log(transform.position + "  " + m_NavMeshPath.corners[m_currentIndex]);
    }


    public void Update()
    {
        var _fx = 1;
        if (Input.GetKey(KeyCode.W))
        {
            GetNav(transform.position + Vector3.forward * _fx);
        }
        if (Input.GetKey(KeyCode.A))
        {
            GetNav(transform.position - Vector3.right * _fx);
        }
        if (Input.GetKey(KeyCode.S))
        {
            GetNav(transform.position - Vector3.forward * _fx);
        }
        if (Input.GetKey(KeyCode.D))
        {
            GetNav(transform.position + Vector3.right * _fx);
        }

        if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.D))
        {
            isUpdate = false;
        }

        //开始导航
        RunToTarget();
    }
}

实现效果截图:

使用WASD即可控制移动。 


总结

 以上就是今天要讲的内容,本文仅仅简单介绍了NavMeshPath的使用,而NavMeshPath提供了大量能使我们快速便捷地处理数据的函数和方法。(吐槽下~官方总结)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot+Vue项目大学校园防疫与服务系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JDK版…

C++初阶 Vector模拟实现

q. > 作者&#xff1a;小萌新 专栏&#xff1a;C初阶 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客介绍&#xff1a;本篇博客会模拟Vector实现 学习目标 模拟默认函数实现模拟迭代器实现模拟容器大小相关函数模拟修改内容相关函数模拟访问容器相关函数 我…

xss挑战之旅11-19关

文章目录前言第11关&#xff1a;referer第12关&#xff1a;User-Agent第13关&#xff1a;cookie第14关&#xff1a;exif xss第15关&#xff1a;ng-include第16关第17关第18关第19关&#xff1a;flash xss前言 靶场&#xff1a;XSS挑战之旅 1-10关 11-20关 第11关&#xff1a;r…

『LeetCode|每日一题』---->颜色填充

目录 1.每日一句 2.作者简介 『LeetCode|每日一题』颜色填充 1.每日一题 2.解题思路 2.1 思路分析&#xff08;DFS&#xff09; 2.2 核心代码 2.3 完整代码 2.4 运行结果 1.每日一句 我的宇宙为你藏着无数个星球 2.作者简介 &#x1f3e1;个人主页&#xff1a;XiaoXiaoChe…

Git之路

文章目录指南介绍实战任务一&#xff1a;sb项目任务二&#xff1a;idea实战任务三&#xff1a;分支实战(待续)指南 如果你想在简历上写“会常用的Git的命令“&#xff0c;那么这篇文章值得你要看&#xff0c;那我们需要掌握什么呢&#xff1f;其实会简单的操作就行&#xff0c…

Matplotlib绘图-快速上手可视化工具

Matplotlib快速上手一、初识Matplotlib1.1 认识Matplotlib的图像结构1.2 绘制一个折线图二、给图像添加修饰2.1 自定义x的刻度2.2一图多线2.3一图绘制多个坐标系子图三、主流图形的绘制3.1绘制柱状图一、初识Matplotlib 是Python最常见的可视化工具之一 1.1 认识Matplotlib的…

csrf跨站请求伪造

文章目录csrf跨站请求伪造1、前戏2、csrf校验2.1、from表单如何符合校验2.2、ajax如何符合校验3、csrf相关装饰器FBVCBVcsrf跨站请求伪造 1、前戏 """ 钓鱼网站搭建一个跟正规网站一摸一样的界面&#xff08;中国银行&#xff09;用户进入到我们的网站&#x…

HyperLynx(三十)高速串行总线仿真(二)

高速串行总线仿真&#xff08;二&#xff09; 仿真实例 1.探索多层板中的PCI-E串行通道 2.设置叠层以减小损耗 3.分析通道的不同配置对损耗的影响 4.检测驱动端规范 5.检查接收器规范 6.通过仿真得出整个通道的驱动约束限制 1.探索多层板中的PCI-E串行通道 在本节练习中&…

人工智能学习:Microsoft COCO数据集读取(7)

Microsoft COCO&#xff08;Common Objects in Context&#xff09;是微软研发维护的一个大型的数据集。包含了30多万张图片和91个目标分类。可用于目标识别&#xff08;Object Detection&#xff09;、场景感知&#xff08;Penoptic Segmentation&#xff09;、语义分割&#…

【数据结构】——单链表

目录 1.链表 1.1 链表的概念及结构 1.2 链表的分类 1. 单向或者双向 2. 带头或者不带头 3. 循环或者非循环 1.3实现一个单链表&#xff08;无头单项非循环链表增删查改的实现&#xff09; 1.链表结构的创建 2.创建一个节点 3.创建一个链表 4.打印链表 5…

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

大家好&#xff0c;又见面了。 在前面的几篇文章中&#xff0c;我们一起聊了下本地缓存的动手实现、本地缓存相关的规范等&#xff0c;也聊了下Google的Guava Cache的相关原理与使用方式。比较心急的小伙伴已经坐不住了&#xff0c;提到本地缓存&#xff0c;怎么能不提一下“地…

软考 - 程序语言设计

程序设计语言基本概述 程序设计语言是为了书写计算机程序而人为设计的符号语言&#xff0c;用于对计算过程进行 描述、组织和推导。 低级语言&#xff1a;机器语言&#xff08;计算机硬件只能识别0和1的指令序列&#xff09;&#xff0c;汇编语言。 高级语言&#xff1a;功能…

从http请求过程分析为何不同业务的http请求都可以使用默认的缺省端口80,8080等

问题: http上传请求时url地址中一般无显示指定端口号&#xff0c;这时会使用默认的80端口&#xff1b;但是可能不止一个业务需要用到http请求&#xff0c;技术上web服务端那边肯定无法根据业务逻辑的数据格式去分别解析区分它们&#xff1b;因为业务是事先无法预知的&#xff…

【Spring Cloud实战】Consul服务注册与发现

个人博客上有很多干货&#xff0c;欢迎访问&#xff1a;https://javaxiaobear.gitee.io/ 1、简介 https://www.consul.io/docs/intro Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation f…

Flink-经典案例WordCount快速上手以及安装部署

2 Flink快速上手 2.1 批处理api 经典案例WordCount public class BatchWordCount {public static void main(String[] args) throws Exception {//1.创建一个执行环境ExecutionEnvironment env ExecutionEnvironment.getExecutionEnvironment();//2.从文件中读取数据//得到…

[附源码]java毕业设计基于Web留学管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux下C++开发笔记--编译静态链接库和动态链接库

目录 1--前言 2--生成静态链接库 3--生成动态链接库 1--前言 承接上一篇Linux下C开发笔记&#xff08;g命令的使用笔记&#xff09;&#xff0c;依据教程记录学习笔记。 2--生成静态链接库 ①回顾项目结构&#xff1a; ​ ②汇编&#xff0c;生成swap.o文件 cd srcg sw…

基于simulink的牛鞭效应模型建模与仿真

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 牛鞭效应&#xff0c;是经济学中的一个术语&#xff0c;它也被称为需求放大效应。牛鞭效应指的是当信息流从最终客户端传输到原始供应商时&…

9.行为建模(Behavioral modeling)

9.1行为模型概述 Verilog行为模型包含控制模拟和操纵先前描述的数据类型变量的过程语句。这些语句包含在程序中。每个过程都有一个与其关联的活动流。活动开始于initial和always语句。每个initial语句和每个always语句都会启动一个单独的活动流。所有活动流都是并发的&…

【机器学习】线性分类【上】广义线性模型

主要参考了B站UP主“shuhuai008”&#xff0c;包含自己的理解。 有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 由于字数限制&#xff0c;分成两篇博客。 【机器学习】线性分类【上】广义线性模型 【机器学习】线性分类【下】经典线性分类算法 1. 线…