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


    系列文章目录

    Navemesh寻路系列文章



    前言

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

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


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

    一、NavMeshPath是什么?

    由导航系统计算的路径。

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

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

    二、使用步骤

    1.引入库

    代码如下:

    1. using UnityEngine;
    2. using UnityEngine.AI;

    2.读入数据

    代码如下(示例):

      NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);
    

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

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

    完整代码如下:

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. ///
    6. /// 人物平滑移动器
    7. ///
    8. public class AgentMove : MonoBehaviour
    9. {
    10. public float speed = 0.5f;
    11. // Start is called before the first frame update
    12. void Start()
    13. {
    14. NavMeshAgent = transform.gameObject.GetComponent();
    15. m_NavMeshPath = new NavMeshPath();
    16. }
    17. private NavMeshAgent NavMeshAgent;
    18. private NavMeshPath m_NavMeshPath;
    19. ///
    20. /// 前一个路径点索引
    21. ///
    22. private int m_previousIndex = 0;
    23. ///
    24. /// 后一个路径点索引
    25. ///
    26. private int m_currentIndex = 1;
    27. private bool isUpdate = false;
    28. void GetNav(Vector3 _pos)
    29. {
    30. isUpdate = true;
    31. Debug.LogError(transform.position + " " + _pos);
    32. transform.LookAt(_pos);
    33. //计算NavMeshPath
    34. NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);
    35. //初始化路径点索引
    36. m_previousIndex = 0;
    37. m_currentIndex = 1;
    38. //if (m_NavMeshPath.corners.Length>1)
    39. //transform.position = m_NavMeshPath.corners[m_CurrentPathPointIndex];
    40. //Debug.Log(m_NavMeshPath.corners[m_CurrentPathPointIndex]+" "+ m_NavMeshPath.corners.Length);
    41. }
    42. ///
    43. /// 移动到目标点(NavMeshPath.corners第0个路径点是当前游戏物体所在位置,以此类推)
    44. ///
    45. public void RunToTarget()
    46. {
    47. isUpdate = m_currentIndex <= m_NavMeshPath.corners.Length - 1;
    48. //防止数组越界
    49. if (!isUpdate) return;
    50. var _pos = transform.position;
    51. _pos.y = m_NavMeshPath.corners[m_currentIndex].y;
    52. //如果游戏物体坐标与当前路径点坐标距离小于0.1即可认为已抵达,可以向下一个路径点导航
    53. if ((_pos - m_NavMeshPath.corners[m_currentIndex]).magnitude <= 0.1f)
    54. {
    55. //递增路径点索引
    56. m_previousIndex++;
    57. m_currentIndex++;
    58. //防止数组越界
    59. if (m_currentIndex > m_NavMeshPath.corners.Length - 1)
    60. {
    61. //Debug.LogError(m_NavMeshPath.corners[m_CurrentPathPointIndex]);
    62. //处理动画切换,请无视
    63. return;
    64. }
    65. //处理人物转向,请无视
    66. }
    67. //匀速运动。计算出前一个路径点到当前路径点方向,然后移动
    68. transform.Translate(
    69. ((-m_NavMeshPath.corners[m_previousIndex] +
    70. m_NavMeshPath.corners[m_currentIndex]).normalized) *
    71. (/*Time.deltaTime **/ speed/* *2f*/), Space.World);
    72. Debug.Log(transform.position + " " + m_NavMeshPath.corners[m_currentIndex]);
    73. }
    74. public void Update()
    75. {
    76. var _fx = 1;
    77. if (Input.GetKey(KeyCode.W))
    78. {
    79. GetNav(transform.position + Vector3.forward * _fx);
    80. }
    81. if (Input.GetKey(KeyCode.A))
    82. {
    83. GetNav(transform.position - Vector3.right * _fx);
    84. }
    85. if (Input.GetKey(KeyCode.S))
    86. {
    87. GetNav(transform.position - Vector3.forward * _fx);
    88. }
    89. if (Input.GetKey(KeyCode.D))
    90. {
    91. GetNav(transform.position + Vector3.right * _fx);
    92. }
    93. if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.D))
    94. {
    95. isUpdate = false;
    96. }
    97. //开始导航
    98. if(isUpdate)RunToTarget();
    99. }
    100. }

    实现效果截图:

    使用WASD即可控制移动。 


    总结

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

  • 相关阅读:
    [JQ][属性]【css】
    可观测性不止于监控,让运维不开盲盒!
    pytorch之nn.Conv1d详解
    kafka 动态扩容现有 topic 的分区数和副本数
    全面讲解,使用Python搭建自己的后端服务(FastAPI),并提供API接口
    React 函数组件
    SpringCloud微服务 【实用篇】| 认识微服务
    攻防世界-web-wzsc_文件上传
    elementplus、vxe、surely 三种表格组件的封装
    4、Jvm(栈)
  • 原文地址:https://blog.csdn.net/Tel17610887670/article/details/127862079