1.新建两个平面
大平面上面包裹着小平面,将小平面重命名为water
并将大平面和小平面模式都改为静态导航
同时新建材质,将小平面设置为蓝色,模拟水。
2.新建胶囊体
把胶囊体当做人物
在胶囊体上添加导航网格代理
3.打开导航配置窗口
窗口选项卡-AI-导航,在右侧就会有导航窗口,可以进行配置
4.给water小平面配置导航
先给phane大平面烘焙bake一下,使之胶囊体是可以在这个大平面内移动的。大平面的成本值为1,而小平面的成本值为4,所以胶囊体在移动的时候,点击鼠标获取最终到达的点位的时候会走最优路线去到达。如果直接穿过小平面到达的话,你也可以给小平面添加导航网格障碍
在water小平面上新建一个成本,成本名称设置为water,成本值设置为3,当成本值越高的时候,人物就会绕开它。
设置区域成本完成后,一定要将它Bake一下,同时你也可以显而易见的看到你设置的区域的颜色和你新建的成本名称对应的颜色是一致的。
选择设置好的water对象,作用就是将设置好的成本绑定到water小平面上,在对象一栏中进行选择water
注意点:以上设置的代理、区域(成本值)、烘焙、对象都是建立在你左侧点击选择的物体身上,比如说在这里,我们选择了小平面water进行设置了区域、烘焙、对象。
5.编写character脚本文件
将脚本文件挂载到胶囊体人物身上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class character : MonoBehaviour
{
//拿到导航代理
NavMeshAgent agent;
Ray ray; //光线
RaycastHit hit;//碰撞信息收集器
GameObject camera;
void Start()
{
agent = GetComponent<NavMeshAgent>();
camera = GameObject.FindWithTag("MainCamera");
}
// 点击鼠标--获取鼠标点击的位置--使用射线--获取和平面交叉的点,
// 这个点就是我们需要的移动目标点
void Update()
{
//鼠标左键点击
if (Input.GetMouseButtonDown(0))
{
//创建一条射线 Input.mousePosition点击的坐标
ray = camera.GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
bool res = Physics.Raycast(ray, out hit);
if (res)
{
Debug.Log("碰撞了");
//物体移动到当前的点位 参数hit.point--获取当前碰撞的点位信息
agent.SetDestination(hit.point);
}
}
}
}
6.最终效果如下:
实现效果:当鼠标点击任意大平面的任意位置的时候,胶囊体会自动到达指定位置,同时因为给小平面water设置了导航,并添加了成本值,使得胶囊体在行走的时候会自动避开water小平面,如果你不加的话,胶囊体会直接传过去。
注意点:大平面也是进行烘焙了的,成本值为1,每次设置完成后都要进行烘焙,可以每次设置完后进行颜色的对比,并且小平面是添加了成本,为water,值为4,所以胶囊体是处在成本值为1和4的上面进行移动。
2.桥梁案例
1.搭建桥梁
新建立方体和圆柱,把一个简易的桥梁搭建好,效果如下:
2.设置为静态导航
除了胶囊体(要移动的人物),其他的都要勾选为静态导航
此时我们给平面烘焙bake一下,会发现平面变颜色了,表示你平面设置了烘焙效果
3.新增区域,设置成本值
给平面plane添加一个新的区域,名称为other,成本值为100,这时候烘焙一下,会发现颜色也会发现改变
相应的烘焙属性设置如下:
- 代理半径:越来越小,留白的区域也会变小
- 代理高度:表示物体能穿过去的可接受高度,代理高度越小,表示物体更容易穿过去
- 最大坡度:坡度越小,表示坡度越高,人物上不去
- 步高:决定了物体能够上升的高度
4.编写脚本文件player
将player脚本文件挂载到player胶囊体身上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class player : MonoBehaviour
{
//获取导航网格
NavMeshAgent nav;
void Start()
{
nav = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool res = Physics.Raycast(ray, out hit);
//鼠标左键按下并且结果为真
if(Input.GetMouseButtonDown(0) && res)
{
//要保证物体身上是有碰撞器的。否则没用
nav.SetDestination(hit.point);
}
}
}
烘焙总预览如下:
物体行走的路线:由你烘焙出来的成本值大小决定的,值越小,物体会优先走。(如果有白色区域,物体是走不过去的,相对于一个障碍物)