鸟语天空
NavMeshAgent
post by:追风剑情 2014-8-13 21:57

https://docs.unity3d.com/cn/2019.4/Manual/class-NavMeshAgent.html

注意:NavMeshAgent 与 Rigidbody 同时挂在角色身上会引起抖动。

一、搭建一个场景

场景设计.png

二、设置不可走区域

设置NavigationStatic.png

三、烘焙不可走区域

烘焙不可走区域.png

点Bake按钮执行烘焙。

四、烘焙可走区域

烘焙可走区域.png

Unity 2019: Window->AI->Navigation

点Bake按钮执行烘焙。

设置哪些层之间要进行碰撞检测 [Edit]->Project Settings->Physics

1111.png

五、编写以下脚本并挂到主角对象上。


using UnityEngine;
using System.Collections;

public class NavMeshAgentTest : MonoBehaviour {

    public NavMeshAgent agent;
    Vector3 point;

    Ray aray;
    RaycastHit ahit;

	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            aray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(aray, out ahit))
            {
                point = ahit.point;
            }
            agent.SetDestination(point);
        }
	}
}


六、运行测试

鼠标点地面,小球会自动绕过建筑移动到鼠标点击点。

寻路运行效果.png

1111.png

NavMeshAgent组件
属性 描述
Base offset
碰撞圆柱体相对于变换轴心点的偏移。
Speed
最大移动速度(以世界单位/秒表示)。
Angular Speed
最大旋转速度(度/秒)。如果要用代码控制转向,需要将此值设置为0或设置NavMeshAgent.updateRotation=false。
Acceleration
最大加速度(以世界单位/平方秒表示)。
Stopping Distance
当靠近目标位置的距离达到此值时,代理将停止。
Auto Braking
启用此属性后,代理在到达目标时将减速。对于巡逻等行为(这种情况下,代理应在多个点之间平滑移动)应禁用此属性。
Radius
代理的半径,用于计算障碍物与基他代理之间的碰撞。
Height
代理通过头顶障碍物时所需的高度间隙。
Quality
障碍躲避质量。如果拥有大量代理,则可以通过降低障碍躲避质量来节省 CPU 时间。如果将躲避设置为无,则只会解析碰撞,而不会尝试主动躲避其他代理和障碍物。
Priority
执行避障时,此代理将忽略优先级较低的代理。该值应在 0–99 范围内,其中较低的数字表示较高的优先级。
Auto Traverse Off Mesh Link
设置为 true 可自动跨越网格外链接 (Off-Mesh Link),即NavMeshAgent到达OffMeshLink端点时会自动瞬移到另一端。如果要使用动画或某种特定方式跨越网格外链接,则应关闭此功能。
Auto Repath
启用此属性后,代理将在到达部分路径末尾时尝试再次寻路。当没有到达目标的路径时,将生成一条部分路径通向与目标最近的可达位置。
Area Mask
描述了代理在寻路时将考虑的区域类型。在准备网格进行导航网格烘焙时,可设置每个网格区域类型。例如,可将楼梯标记为特殊区域类型,并禁止某些角色类型使用楼梯。


NavMeshAgent类
属性 描述
isOnOffMeshLink 判断NavMeshAgent是否正处于OffMeshLink上面。
autoTraverseOffMeshLink true: 当NavMeshAgent到达OffMeshLink端点时,将自动瞬移到另一端。false: 需要程序员自己处理移动。
autoBraking 启用此属性后,代理在到达目标时将减速。对于巡逻等行为(这种情况下,代理应在多个点之间平滑移动)应禁用此属性。
autoRepath 启用此属性后,代理将在到达部分路径末尾时尝试再次寻路。当没有到达目标的路径时,将生成一条部分路径通向与目标最近的可达位置。
hasPath NavMeshAgent是否已生成了一条路径。
pathPending NavMeshAgent是否正在计算路径。
isPathStale 当前路径是否已过时。
pathStatus 当前路径的状态(完整、部分或无效)。
pathEndPosition 当前路径的终点坐标。
isStopped true: 停止寻路,false:恢复寻路
path 当前路径信息
nextOffMeshLinkData 当前路径下一个OffMeshLink数据信息
navMeshOwner 返回代理当前放置在上面的导航网格的拥有对象
walkableMask 已过时,参见 areaMask
areaMask 指定哪些层可行走
speed NavMeshAgent最大移动速度
angularSpeed 最大转向速度。(度/秒)
acceleration 最大加速度 。(米/秒平方)
updatePosition true: 允许NavMeshAgent自动更新坐标,如果需要手动控制移动,需要关闭这个属性。
updateRotation true: 允许NavMeshAgent自动更新旋转,如果需要手动控制旋转,需要关闭这个属性。
updateUpAxis true: NavMeshAgent与世界坐标系Y轴对齐,false: NavMeshAgent垂直于导航面。
radius 代理半径
height 代理高度
obstacleAvoidanceType 规避品质级别
agentTypeID 代理类型ID
currentOffMeshLinkData 当前OffMeshLink数据信息。通常先判断isOnOffMeshLink为true,然后再获取currentOffMeshLinkData。
isOnNavMesh 判断NavMeshAgent是否已绑定到导航层上。
baseOffset NavMeshAgent相对于它的的GameObject垂直偏移量
remainingDistance NavMeshAgent离终点的剩余距离
desiredVelocity 此速度值会受各种条件影响,如躲避动态障碍。
steeringTarget NavMeshAgent当前转向,即目标方位。当updateRotation=false时,可手动使用transform.LookAt(steeringTarget)让角色朝向与行走方向一至。
nextPosition 当updatePosition=false时,可在Update方法中手动设置位置。transform.position=navMeshAgent.nextPosition;
velocity 代理当前速度
stoppingDistance 离终点多远停止移动。比如要让玩家导航到某个NPC身旁时,可将此值设置为0.2,从而避免与NPC重叠。
destination 终点坐标。也可以用SetDestination()方法设置终点。
avoidancePriority 规避优先级
方法 描述
void ActivateCurrentOffMeshLink(bool activated) 启用或禁用当前的网格外链接
bool CalculatePath(Vector3 targetPosition, NavMeshPath path) 计算到指定点的路径并存储路径
void CompleteOffMeshLink() 代理将移动到当前 OffMeshLink 另一端上最近的有效导航网格位置。代理需要在OffMeshLink上,否则调用此函数无任何效果。
bool FindClosestEdage(out NavMeshHit hit) 找到最近的导航网格边缘
float GetAreaCost(int areaIndex) 获取在跨越特定类型的区域时的路径计算成本
float GetLayerCost(int layer) 已过时,使用GetAreaCost()代替。
void Move(Vector3 offset) 手动移动代理(相对移动)
bool Raycast(Vector3 targetPosition, out NavMeshHit hit) 检查代理与目标点之间是否有障碍
void ResetPath() 清除当前路径
void Resume() 已过时,用isStopped=false代替
bool SamplePathPosition(int areaMask, float maxDistance, out NavMeshHit hit) 沿着当前路径检查。通过此方法可提前知道前方路段信息。
void SetAreaCost(int areaIndex, float areaCost) 设置遍历指定类型区域的成本。代理被禁用时areaCost会被重置。
bool SetDestination(Vector3 target) 设置终点,并重新计算路径。
void SetLayerCost(int layer, float cost) 已过时,用SetAreaCost()代替。
bool SetPath([NotNull] NavMeshPath path) 为代理分配一条新路径。
void Stop(bool stopUpdates) 已过时,使用isStopped代替
void Stop() 已过时,使用isStopped=true代替
bool Warp(Vector3 newPosition) 将代理移动到指定位置


updateUpAxis 说明

22222.png22222.png

问题:解决NavMeshAgent转向缓慢问题

using UnityEngine;
using UnityEngine.AI;
/// <summary>
/// NavMeshAgent的旋转太慢
/// 可用此脚本替换NavMeshAgent的旋转功能
/// 将此脚本挂在和NavMeshAgent同一GameObject上
/// </summary>
public class NavMeshAgentRotation : MonoBehaviour
{
    [SerializeField]
    private NavMeshAgent navMeshAgent;
    public float angularSpeed = 10f;
    private Transform mTransform;

    private void Awake()
    {
        mTransform = transform;
        if (navMeshAgent == null)
            navMeshAgent = this.GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        if (navMeshAgent == null)
            return;
        //代理是否绑定到导航网格
        if (!navMeshAgent.isOnNavMesh)
            return;
        if (navMeshAgent.isStopped || navMeshAgent.pathPending || !navMeshAgent.hasPath)
            return;
        //当处于斜坡上时,由于NavMeshAgent与动画重力权重(gravityWeight)之间存在冲突,会发生抖动现象。
        navMeshAgent.updateRotation = false;
        //关闭寻路避免抖动
        navMeshAgent.isStopped = navMeshAgent.remainingDistance < 0.1f;

        /* 手动控制旋转 */
        //当前朝向
        Quaternion forward = Quaternion.identity;
        forward.SetLookRotation(mTransform.forward);
        //目标朝向
        Vector3 targetForward = navMeshAgent.steeringTarget - mTransform.position;
        Quaternion steering = Quaternion.identity;
        steering.SetLookRotation(targetForward);
        //旋转插值
        Quaternion rotation = Quaternion.Lerp(forward, steering, Time.deltaTime * angularSpeed);
        mTransform.rotation = rotation;
    }
} 
评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容