问题已关闭
与已有问题相似
问题已重定向至
大神们,在使用Unity做赛车类游戏时 ,AI自动寻路时 ,你们是怎么处理的呢?
大神们,在使用Unity做赛车类游戏时 ,AI自动寻路时 ,你们是怎么处理的呢?路点的设置有什么技巧吗?求指教,谢谢~~~
已有帐号?
无法登录?
社交帐号登录Unity3D教程:角色控制–点击移动以及自动寻路(上) | Unity3D教程手册
当前位置 :
>> Unity3D教程:角色控制–点击移动以及自动寻路(上)
Unity3D教程:角色控制–点击移动以及自动寻路(上)
首先需要解决几个问题:
1.如何取得目标地点。
需要通过鼠标当前位置的屏幕二维坐标,逆矩阵变换到世界空间下,做从摄像机到这个点的射线。射线与地面mesh进行碰撞检测,获得一个交点,就是目标点。
2.如何移动角色。
实时得出角色的移动方向向量,在两点之间做线性插值计算,移动的同时也要播放动画。
3.两点之间有障碍怎么办?
这个过程是一个比较复杂的过程,可以通过两种办法,一种是做一种转向机制,先移动监测点(我自己起的,意思是一个前进向量和一个向下的碰撞向量的假象交点),监测到碰撞了,就将角色转向,再次监测,直到碰撞不到,向当前挪一步,再重复刚才的操作,直到绕过这个障碍物;另一种是俗称的A*算法,需要预先准备好一个二维图来标记哪里可以走,哪里不可以走,并设置权值,以便于计算最短路径。
4.Unity3D里的碰撞需要注意什么?
射线的碰撞检测是比较耗费CPU资源的,推荐的是尽量少用,比如当做场景内物体的鼠标拾取时,对备选对象队列进行筛选后,再去逐一做检测。unity3d中也是一样,只不过没有提供像DX中提供的那种API,无法用自定义的结构去决定对哪些对象进行射线碰撞。所以要引入Layer的概念,具体的操作下节说。
针对上面第4点--筛选待测物体来说一下U3D中Layer的用法。
U3D中的Layer可以简单地理解为一个集合,所有的GameObject都可以设置Layer,且只能设置一个Layer。
设置方法:
1.Edit-&Project Setting-&Tags(tag和layer在同一个设置面板上)。
2.前几个Builtin Layer是系统默认的,不能修改,可以在后面几个Layer中,设置Layer的名称,比如"Players"。
3.在Hierarchy面板中选择GameObject,在Inspector面板上面的Layer下拉框中选择刚才设置好的Layer。
从此,该GameObject就属于这个Layer集合中的一员了。
Layer的应用:LayerMask
LayerMask可以在射线碰撞过程中屏蔽掉一些GameObject。
LayerMask的方法:
LayerMask.NameToLayer("Players") 返回该Layer的编号。
LayerMask.LayerToName(8) 返回该Layer的名称。
var layerMaskPlayers:LayerMask = 1 && LayerMask.NameToLayer("Players");
var layerMaskTerrains:LayerMask = 1 && LayerMask.NameToLayer("Terrains");
var FinalMask:LayerMask
= (layerMaskPlayers.value | layerMaskTerrains.value);
var hitt : RaycastH
var ray : Ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if( Physics.Raycast(ray,
hitt, 600, FinalMask.value))
上面代码描述一个鼠标拾取规则,射线仅与Layer属于Players和Terrains的GameObject做碰撞。
LayerMask的使用是按位操作的,在设置新的Layer时可以看到一共只有32个,应该是因为记录Layer的变量是四个字节。LayerMask.NameToLayer方法返回的LayerId是所要移位的位数,比如在设置Layer时,Players这个Layer的ID是8,则:
var layerMaskPlayers:LayerMask = 1 && LayerMask.NameToLayer("Players");
最后将所有的可能按位或操作,就得出所有需要做射线碰撞的GameObject。
如果想取“除了XXXLayer”的都显示,则可以用取反操作。
layerMaskPlayers = ~layerMaskPlayers.
比如:layerMaskPlayers = 1&&8;
则:layerMaskPlayers = ;
在双字长的情况下,~layerMaskPlayers.value = -257
二进制表示:
为鼠标点击的位置增加一个光圈。需求如下:
鼠标右键点击地面,射线与地面的交点处出现一个光圈(纹理动画)。
该纹理动画会旋转,跟游戏中一样。
玩家移动到该光圈处,或者进入了其他状态,光圈消失。
玩家点击新的目标点,原目标点光圈消失。
光圈要随着地形的起伏改变自己的朝向,这样自然。
制作过程:
首先create一个Plane,去掉这个Plane的Collider Component,否则玩家会和光圈点发生碰撞。并为这个Plane指定一个纹理贴图,shader方式选择Particles/Alpha Blended Premultiply 颜色相乘,显得光圈亮一些。注意光圈图片必须要有Alpha通道,才能进行透明处理。
然后在全局空GameObject(空的对象,不做任何逻辑处理,只为了挂接全局的脚本--不依附于任何Object的脚本)中增加一个鼠标相关控制脚本。加上前面所说过的改变鼠标指针UI操作,整个脚本如下:
这个脚本要完成的工作是:
通过传进来的prefab(transform类型),将光圈点放置在指定位置,并且根据射线与地形交点的面片的法线,调整这个光圈的朝向。还有一个在创建时要注意的是,将光圈的坐标沿着Y轴正向提高了一个数值,是为了避免纹理动画与地面纹理重合造成撕裂现象。
其中定义的两个方法CreateDestinationTex和DestroyDestinationTex将会在人物控制脚本中调用。
注:虽然Instantiate方法在手册中显示返回的类型是Object,但实际上是返回跟prefab同类型的一个对象,比如prefab是个transform类型,那么Instantiate返回的就是一个transform类型的对象,在Destroy一个prefeb对象时,Destroy(...) 括号里只能写Object或GameObject,如果是Transform,则会因为有其他Component依附于这个transform,而无法删除掉。
最后修改角色控制脚本,在其中获得鼠标控制脚本的对象:
private var _ScriptObj_cursorControl :
_ScriptObj_cursorControl = GameObject.Find("GameObject_GlobalController").GetComponent(Script_Cursor); //获得鼠标图标脚本对象
然后在鼠标右键点击地面后,进入STATE_LERPWALK状态,同时调用鼠标控制脚本中的函数CreateDestinationTex在指定给位置创建一个光圈对象,而当不在STATE_LERPWALK状态下时,调用鼠标控制脚本中的函数DestroyDestinationTex删除该对象。
注:虽然Instantiate方法在手册中显示返回的类型是Object,但实际上是返回跟prefab同类型的一个对象,比如prefab是个transform类型,那么Instantiate返回的就是一个transform类型的对象,在Destroy一个prefeb对象时,Destroy(...) 括号里只能写Object或GameObject,如果是Transform,则会因为有其他Component依附于这个transform,而无法删除掉。
最后修改角色控制脚本,在其中获得鼠标控制脚本的对象:
private var _ScriptObj_cursorControl :
_ScriptObj_cursorControl = GameObject.Find("GameObject_GlobalController").GetComponent(Script_Cursor); //获得鼠标图标脚本对象
然后在鼠标右键点击地面后,进入STATE_LERPWALK状态,同时调用鼠标控制脚本中的函数CreateDestinationTex在指定给位置创建一个光圈对象,而当不在STATE_LERPWALK状态下时,调用鼠标控制脚本中的函数DestroyDestinationTex删除该对象。
if (Input.GetMouseButtonUp (1) && _grounded)
//调用鼠标处理脚本
if(_ScriptObj_cursorControl != null)
//创建目标点光圈
_ScriptObj_cursorControl.CreateDestinationTex(_endPos,TextureOnFloor,_hit.normal);
if(_playerstate == PlayerState.STATE_LERPWALK && _grounded)
if(_ScriptObj_cursorControl != null)
_ScriptObj_cursorControl.DestroyDestinationTex(); // 删除目标点光圈
Debug.Log("cursor scirpt error !");
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!>> unity3d寻路
unity3d寻路
所属分类:
下载地址:
NavMeshTest.zip文件大小:13.84 MB
分享有礼! 》
请点击右侧的分享按钮,把本代码分享到各社交媒体。
通过您的分享链接访问Codeforge,每来2个新的IP,您将获得0.1 积分的奖励。
通过您的分享链接,每成功注册一个用户,该用户在Codeforge上所获得的每1个积分,您都将获得0.2 积分的分成奖励。
这事一个unity3d的原生源码资源,是学习unity3d的好资源,值得收藏学习!
Sponsored links
源码文件列表
温馨提示: 点击源码文件名可预览文件内容哦 ^_^
.DS_Store6.00 kB 08:04
BlueFlag32.png2.75 kB 12:06
BlueFlag32.png.meta663.00 B 12:06
GreenFlag32.png2.69 kB 08:07
GreenFlag32.png.meta663.00 B 08:08
RedFlag32.png2.63 kB 12:06
RedFlag32.png.meta663.00 B 12:07
Gizmos.meta60.00 B 11:49
BlockBlue.mat4.12 kB 13:03
BlockBlue.mat.meta60.00 B 12:07
BlockDark.mat4.12 kB 12:06
BlockDark.mat.meta60.00 B 12:07
BlockGray.mat4.12 kB 12:06
BlockGray.mat.meta60.00 B 12:07
BlockRed.mat4.12 kB 13:03
BlockRed.mat.meta60.00 B 11:49
Block.meta60.00 B 11:49
Blue.mat4.11 kB 12:06
Blue.mat.meta60.00 B 12:07
defaultMat.mat4.12 kB 16:21
defaultMat.mat.meta60.00 B 16:21
Green.mat4.11 kB 09:12
Green.mat.meta60.00 B 09:11
Red.mat4.11 kB 12:06
Red.mat.meta60.00 B 12:07
Materials.meta60.00 B 11:49
Soldier@Idle.FBX5.75 MB 11:48
Soldier@Idle.FBX.meta8.81 kB 11:50
Soldier@Standing.FBX1.81 MB 11:49
Soldier@Standing.FBX.meta8.81 kB 11:50
Soldier@StandingAim.FBX508.41 kB 11:49
Soldier@StandingAim.FBX.meta8.82 kB 11:50
Soldier@StandingFire.FBX534.98 kB 11:48
Soldier@StandingFire.FBX.meta8.82 kB 11:50
Soldier@StandingFireRPG.FBX745.17 kB 11:48
Soldier@StandingFireRPG.FBX.meta8.82 kB 11:50
Soldier@StandingReloadM4.FBX1.73 MB 11:49
Soldier@StandingReloadM4.FBX.meta8.98 kB 11:50
Soldier@StandingReloadRPG1.FBX1.45 MB 11:48
Soldier@StandingReloadRPG1.FBX.meta8.82 kB 11:50
Idle_Standing_Anims.meta60.00 B 11:49
Soldier@RunJump.FBX1.46 MB 11:48
Soldier@RunJump.FBX.meta8.79 kB 11:50
Soldier@StandingJump.FBX694.84 kB 11:48
Soldier@StandingJump.FBX.meta8.78 kB 11:50
Soldier_JumpLanding.fbx1.37 MB 11:49
Soldier_JumpLanding.fbx.meta9.23 kB 11:49
Soldier_RunJump2.FBX1.16 MB 11:49
Soldier_RunJump2.FBX.meta9.26 kB 11:49
new.meta60.00 B 11:49
Jump_Anims.meta60.00 B 11:49
No4.11 kB 12:06
No60.00 B 12:07
Materials.meta60.00 B 11:49
Soldier_Ladder.FBX27.69 kB 11:49
Soldier_Ladder.FBX.meta1.80 kB 11:49
Soldier_Ladder_Down.FBX2.46 MB 11:49
Soldier_Ladder_Down.FBX.meta9.26 kB 11:49
Soldier_Ladder_Up.FBX2.28 MB 11:49
Soldier_Ladder_Up.FBX.meta9.25 kB 11:50
Ladder_Anims.meta60.00 B 11:49
lambert2.mat4.11 kB 12:06
lambert2.mat.meta60.00 B 12:07
m4-lambert2.mat3.52 kB 11:49
m4-lambert2.mat.meta60.00 B 11:49
polySurface1SG.mat4.12 kB 12:06
polySurface1SG.mat.meta60.00 B 12:07
polySurface1SG1.mat4.12 kB 12:06
polySurface1SG1.mat.meta60.00 B 12:07
soldier-body.mat3.71 kB 11:49
soldier-body.mat.meta60.00 B 11:49
soldier-head.mat3.57 kB 11:48
soldier-head.mat.meta60.00 B 11:49
Materials.meta60.00 B 11:49
Soldier@Run.FBX754.33 kB 11:49
Soldier@Run.FBX.meta8.81 kB 11:50
Soldier@RunAim.FBX753.56 kB 11:48
Soldier@RunAim.FBX.meta8.81 kB 11:50
Soldier@RunBackwards.FBX753.88 kB 11:48
Soldier@RunBackwards.FBX.meta8.82 kB 11:50
Soldier@RunBackwardsAim.FBX753.34 kB 11:48
Soldier@RunBackwardsAim.FBX.meta8.82 kB 11:50
Soldier@RunBackwardsFire.FBX757.77 kB 11:48
Soldier@RunBackwardsFire.FBX.meta8.82 kB 11:50
Soldier@RunFire.FBX758.08 kB 11:48
Soldier@RunFire.FBX.meta8.81 kB 11:50
Soldier@RunFireRPG.FBX758.23 kB 11:48
Soldier@RunFireRPG.FBX.meta8.82 kB 11:50
Soldier@StrafeRunLeft.FBX751.27 kB 11:49
Soldier@StrafeRunLeft.FBX.meta8.82 kB 11:50
Soldier@StrafeRunLeftAim.FBX751.70 kB 11:48
Soldier@StrafeRunLeftAim.FBX.meta8.82 kB 11:50
Soldier@StrafeRunLeftFire.FBX969.11 kB 11:49
Soldier@StrafeRunLeftFire.FBX.meta8.82 kB 11:50
Soldier@StrafeRunRight.FBX957.33 kB 11:49
Soldier@StrafeRunRight.FBX.meta8.82 kB 11:50
Soldier@StrafeRunRightAim.FBX751.38 kB 11:49
Soldier@StrafeRunRightAim.FBX.meta8.82 kB 11:50
Soldier@StrafeRunRightFire.FBX756.59 kB 11:49
Soldier@StrafeRunRightFire.FBX.meta8.82 kB 11:50
Run_Anims.meta60.00 B 11:49
Soldier.fbx3.34 MB 11:49
Soldier.fbx.meta9.05 kB 11:49
Soldier_LOD2.fbx5.41 MB 17:30
Soldier_LOD2.fbx.meta9.01 kB 18:40
Soldier@RelaxedWalk.FBX1,008.55 kB 11:48
Soldier@RelaxedWalk.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkLeft.FBX1,009.47 kB 11:49
Soldier@StrafeWalkLeft.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkLeftAim.FBX1,009.70 kB 11:49
Soldier@StrafeWalkLeftAim.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkLeftFire.FBX1.38 MB 11:49
Soldier@StrafeWalkLeftFire.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkRight.FBX1,009.20 kB 11:48
Soldier@StrafeWalkRight.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkRightAim.FBX1,008.95 kB 11:49
Soldier@StrafeWalkRightAim.FBX.meta8.82 kB 11:50
Soldier@StrafeWalkRightFire.FBX1,010.58 kB 11:48
Soldier@StrafeWalkRightFire.FBX.meta8.83 kB 11:50
Soldier@Walk.FBX1,005.98 kB 11:48
Soldier@Walk.FBX.meta8.81 kB 11:50
Soldier@WalkAim.FBX1,006.00 kB 11:48
Soldier@WalkAim.FBX.meta8.81 kB 11:50
Soldier@WalkBackwards.FBX1,005.83 kB 11:49
Soldier@WalkBackwards.FBX.meta8.87 kB 11:50
Soldier@WalkBackwardsAim.FBX1,006.05 kB 11:49
Soldier@WalkBackwardsAim.FBX.meta8.82 kB 11:50
Soldier@WalkBackwardsFire.FBX1,007.97 kB 11:48
Soldier@WalkBackwardsFire.FBX.meta8.82 kB 11:50
Soldier@WalkFire.FBX1,007.91 kB 11:49
Soldier@WalkFire.FBX.meta8.81 kB 11:50
Soldier@WalkFireRPG.FBX1,007.50 kB 11:49
Soldier@WalkFireRPG.FBX.meta8.82 kB 11:50
Walk_Anims.meta60.00 B 11:49
Soldier.meta60.00 B 11:49
spiral.obj12.58 kB 19:54
spiral.obj.meta1.38 kB 16:21
Meshes.meta60.00 B 11:49
agentblue(doors).prefab11.24 kB 08:40
agentblue(doors).prefab.meta60.00 B 14:06
agentred(doors).prefab11.24 kB 08:40
agentred(doors).prefab.meta60.00 B 14:06
BoxBlue.prefab8.26 kB 18:01
BoxBlue.prefab.meta60.00 B 17:55
BoxRed.prefab8.26 kB 18:01
BoxRed.prefab.meta60.00 B 17:58
SoldierBlue.prefab29.66 kB 18:45
SoldierBlue.prefab.meta60.00 B 12:07
SoldierRed.prefab29.66 kB 18:43
SoldierRed.prefab.meta60.00 B 12:07
Agents.meta60.00 B 11:49
doorblue.prefab12.74 kB 08:40
doorblue.prefab.meta60.00 B 14:06
doorgreen.prefab12.75 kB 08:40
doorgreen.prefab.meta60.00 B 14:06
doorred.prefab12.76 kB 08:40
doorred.prefab.meta60.00 B 14:06
Doors.meta60.00 B 08:40
Ladder.prefab8.66 kB 11:48
Ladder.prefab.meta60.00 B 11:49
TargetBlue.prefab8.31 kB 14:41
TargetBlue.prefab.meta60.00 B 12:07
TargetGreen.prefab8.32 kB 09:12
TargetGreen.prefab.meta60.00 B 09:10
TargetRed.prefab8.30 kB 14:41
TargetRed.prefab.meta60.00 B 12:07
TargetBlue.prefab8.24 kB 08:40
TargetBlue.prefab.meta60.00 B 12:07
TargetGreen.prefab8.25 kB 08:40
TargetGreen.prefab.meta60.00 B 09:10
TargetRed.prefab8.24 kB 08:40
TargetRed.prefab.meta60.00 B 12:07
Targets.meta60.00 B 08:40
Prefabs.meta60.00 B 11:49
NavMesh.asset25.30 kB 20:00
NavMesh.asset.meta60.00 B 20:00
bridge.meta60.00 B 07:51
bridge.unity151.68 kB 20:00
bridge.unity.meta60.00 B 19:37
LightmapFar-0.exr1.77 MB 03:03
LightmapFar-0.exr.meta659.00 B 03:03
LightmapFar-1.exr570.39 kB 03:03
LightmapFar-1.exr.meta659.00 B 03:03
LightmapFar-2.exr364.49 kB 03:03
LightmapFar-2.exr.meta659.00 B 03:03
LightmapFar-3.exr489.27 kB 03:03
LightmapFar-3.exr.meta659.00 B 03:03
NavMesh.asset67.89 kB 01:12
NavMesh.asset.meta60.00 B 01:12
cave.meta60.00 B 11:49
cave.unity222.26 kB 07:47
cave.unity.meta60.00 B 03:03
NavMesh.asset6.16 kB 07:47
NavMesh.asset.meta60.00 B 07:47
door1.meta60.00 B 07:46
door1.unity32.04 kB 08:40
door1.unity.meta60.00 B 13:01
NavMesh.asset7.45 kB 07:47
NavMesh.asset.meta60.00 B 07:47
door2.meta60.00 B 13:01
door2.unity39.80 kB 08:18
door2.unity.meta60.00 B 13:06
NavMesh.asset8.13 kB 09:14
NavMesh.asset.meta60.00 B 09:14
door3.meta60.00 B 13:01
door3.unity43.11 kB 09:16
door3.unity.meta60.00 B 13:06
agentblue(doors).prefab11.24 kB 14:06
agentblue(doors).prefab.meta60.00 B 14:06
agentred(doors).prefab11.24 kB 14:06
agentred(doors).prefab.meta60.00 B 14:06
doorblue.prefab12.74 kB 14:06
doorblue.prefab.meta60.00 B 14:06
doorgreen.prefab12.75 kB 14:06
doorgreen.prefab.meta60.00 B 14:06
doorred.prefab12.76 kB 14:06
doorred.prefab.meta60.00 B 14:06
Prefabs.meta60.00 B 19:37
Doors.meta60.00 B 19:37
NavMesh.asset9.71 kB 08:23
NavMesh.asset.meta60.00 B 08:23
plane.meta60.00 B 11:52
plane.unity51.82 kB 08:53
plane.unity.meta60.00 B 03:03
NavMesh.asset4.38 kB 12:01
NavMesh.asset.meta60.00 B 12:01
ring.meta60.00 B 11:57
ring.unity19.85 kB 12:01
ring.unity.meta60.00 B 11:59
ring100.unity19.75 kB 19:37
ring100.unity.meta60.00 B 19:37
ring100_cubes.unity19.73 kB 19:37
ring100_cubes.unity.meta60.00 B 19:37
Scenes.meta60.00 B 11:49
4.25 kB 19:54
agentLocomotion.js.meta165.00 B 13:51
900.00 B 01:47
attractorFlag.js.meta165.00 B 01:46
659.00 B 06:36
DoorClient.cs.meta165.00 B 06:36
1.90 kB 08:51
DoorController.cs.meta165.00 B 13:01
1.81 kB 08:48
DrawBridge.cs.meta165.00 B 03:03
720.00 B 08:48
mouseClickTarget.js.meta165.00 B 13:51
580.00 B 08:49
ringspawn.js.meta165.00 B 12:06
372.00 B 05:37
rotateAround.js.meta165.00 B 18:08
921.00 B 08:18
ToggleTarget.cs.meta165.00 B 05:47
Scripts.meta60.00 B 11:49
AudioManager.asset4.03 kB 03:03
DynamicsManager.asset4.18 kB 03:03
EditorBuildSettings.asset4.04 kB 14:08
EditorSettings.asset4.06 kB 03:03
InputManager.asset5.27 kB 03:03
NavMeshLayers.asset9.02 kB 08:52
NetworkManager.asset4.02 kB 03:03
ProjectSettings.asset10.85 kB 05:38
QualitySettings.asset4.58 kB 14:08
TagManager.asset5.27 kB 03:03
TimeManager.asset4.02 kB 03:03
(提交有效评论获得积分)
评论内容不能少于15个字,不要超出160个字。
评价成功,多谢!
NavMeshTest.zip
CodeForge积分(原CF币)全新升级,功能更强大,使用更便捷,不仅可以用来下载海量源代码马上还可兑换精美小礼品了
您的积分不足,优惠套餐快速获取 30 积分
10积分 / ¥100
30积分 / ¥200原价 ¥300 元
100积分 / ¥500原价 ¥1000 元
订单支付完成后,积分将自动加入到您的账号。以下是优惠期的人民币价格,优惠期过后将恢复美元价格。
支付宝支付宝付款
微信钱包微信付款
更多付款方式:、
您本次下载所消耗的积分将转交上传作者。
同一源码,30天内重复下载,只扣除一次积分。
鲁ICP备号-2 runtime:Elapsed:48.690ms - init:0.3;find:3.4;t:1.6;tags:1.0;related:21.0;comment:0.2; 27.69
登录 CodeForge
还没有CodeForge账号?
Switch to the English version?
^_^"呃 ...
Sorry!这位大神很神秘,未开通博客呢,请浏览一下其他的吧[原]Unity3D深入浅出 - 导航网格自动寻路(Navigation Mesh) - Tonge - 推酷
[原]Unity3D深入浅出 - 导航网格自动寻路(Navigation Mesh) - Tonge
NavMesh(导航网格)是3D游戏世界中用于实现动态物体自动寻路的一种技术,将游戏中复杂的结构组织关系简化为带有一定信息的网格,在这些网格的基础上通过一系列的计算来实现自动寻路。。导航时,只需要给导航物体挂载导航组建,导航物体便会自行根据目标点来寻找最直接的路线,并沿着该线路到达目标点。
下面通过一个简单的Sample来介绍NavMesh的应用:
1.在Scene中新建三个Cube,如下图摆放。
2.选中上图三个Cube,并在Inspector面板中选中为静态(static)下拉选项的Navigation Static,如下图。
3.依次选择菜单栏中的Windows - Navigation ,打开后面板如下。
单击该面板右下角的Bake按钮,即可生成导航网格,下图为已生成的导航网格。
4.下面就可以让一个运动体根据一个导航网格运动到目标位置。
首先新建一个Cube为目标位置,起名TargetCube。然后创建一个capsule(胶囊)运动体,为该胶囊挂在一个Nav Mesh Agent(Component - Navigation - Nav Mesh Agent);最后写一个脚本就可以实现自动寻路了。脚本如下:
using UnityE
using System.C
public class Run : MonoBehaviour {
public Transform TargetObject = null;
void Start () {
if (TargetObject != null)
GetComponent&NavMeshAgent&().destination = TargetObject.
void Update () {
脚本新建完成后挂载到胶囊体上,然后将TargetCube赋予给胶囊体的Run脚本,运行场景,如下图,胶囊体会按照箭头的方向运动到Cube位置。
这样一个简单的自动寻路就完成了,如果要更精细的寻路,或要实现上坡,钻&桥洞&等,可根据下面介绍的相关参数进行调节。
下面介绍 Navigation 组件和 Nav Mesh Agent 组件的相关参数。
Navigation
Object:物体参数面板
Navigation Static:勾选后表示该对象参与导航网格的烘培。
OffMeshLink Generation:勾选后可跳跃(Jump)导航网格和下落(Drop)。
Bake:烘培参数面板
Radius:具有代表性的物体半径,半径越小生成的网格面积越大。
Height:具有代表性的物体的高度。
Max Slope:斜坡的坡度。
Ste Height:台阶高度。
Drop Height:允许最大的下落距离。
Jump Distance:允许最大的跳跃距离。
Min Region Area:网格面积小于该值则不生成导航网格。
Width Inaccuracy:允许最大宽度的误差。
Height Inaccuracy:允许最大高度的误差。
Height Mesh:勾选后会保存高度信息,同时会消耗一些性能和存储空间。
Nav Mesh Agent:导航组建参数面板
Radius:物体的半径
Speed:物体的行进最大速度
Acceleration:物体的行进加速度
Augular Speed:行进过程中转向时的角速度。
Stopping Distance:离目标距离还有多远时停止。
Auto Traverse Off Mesh Link:是否采用默认方式度过链接路径。
Auto Repath:在行进某些原因中断后是否重新开始寻路。
Height:物体的高度。
Base Offset:碰撞模型和实体模型之间的垂直偏移量。
Obstacle Avoidance Type:障碍躲避的的表现登记,None选项为不躲避障碍,另外等级越高,躲避效果越好,同时消耗的性能越多。
Avoidance Priority:躲避优先级。
NavMesh Walkable:该物体可以行进的网格层掩码。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致孙广东 看了看& Unity的官方案例,就顺便看了 wayPoint相关。效果:WaypointProgressTracker.cs& 【固定】WaypointCircuit.cs& 【固定】
using System.C
using UnityE
#if UNITY_EDITOR
using UnityE
namespace UnityStandardAssets.Utility
public class WaypointCircuit : MonoBehaviour
public WaypointList waypointList = new WaypointList();
[SerializeField] private bool smoothRoute =
private int numP
private Vector3[]
private float[]
public float editorVisualisationSubsteps = 100;
public float Length { }
public Transform[] Waypoints
get { return waypointList. }
//this being here will save GC allocs
private int p0n;
private int p1n;
private int p2n;
private int p3n;
private Vector3 P0;
private Vector3 P1;
private Vector3 P2;
private Vector3 P3;
// Use this for initialization
private void Awake()
if (Waypoints.Length & 1)
CachePositionsAndDistances();
numPoints = Waypoints.L
public RoutePoint GetRoutePoint(float dist)
// position and direction
Vector3 p1 = GetRoutePosition(dist);
Vector3 p2 = GetRoutePosition(dist + 0.1f);
Vector3 delta = p2 - p1;
return new RoutePoint(p1, delta.normalized);
public Vector3 GetRoutePosition(float dist)
int point = 0;
if (Length == 0)
Length = distances[distances.Length - 1];
dist = Mathf.Repeat(dist, Length);
while (distances[point] & dist)
// get nearest two points, ensuring points wrap-around start & end of circuit
p1n = ((point - 1) + numPoints)%numP
// found point numbers, now find interpolation value between the two middle points
i = Mathf.InverseLerp(distances[p1n], distances[p2n], dist);
if (smoothRoute)
// smooth catmull-rom calculation between the two relevant points
// get indices for the surrounding 2 points, because
// four points are required by the catmull-rom function
p0n = ((point - 2) + numPoints)%numP
p3n = (point + 1)%numP
// 2nd point may have been the 'last' point - a dupe of the first,
// (to give a value of max track distance instead of zero)
// but now it must be wrapped back to zero if that was the case.
p2n = p2n%numP
P0 = points[p0n];
P1 = points[p1n];
P2 = points[p2n];
P3 = points[p3n];
return CatmullRom(P0, P1, P2, P3, i);
// simple linear lerp between the two points:
p1n = ((point - 1) + numPoints)%numP
return Vector3.Lerp(points[p1n], points[p2n], i);
private Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float i)
// comments are no use here... it's the catmull-rom equation.
// Un-magic this, lord vector!
return 0.5f*
((2*p1) + (-p0 + p2)*i + (2*p0 - 5*p1 + 4*p2 - p3)*i*i +
(-p0 + 3*p1 - 3*p2 + p3)*i*i*i);
private void CachePositionsAndDistances()
// transfer the position of each point and distances between points to arrays for
// speed of lookup at runtime
points = new Vector3[Waypoints.Length + 1];
distances = new float[Waypoints.Length + 1];
float accumulateDistance = 0;
for (int i = 0; i & points.L ++i)
var t1 = Waypoints[(i)%Waypoints.Length];
var t2 = Waypoints[(i + 1)%Waypoints.Length];
if (t1 != null && t2 != null)
Vector3 p1 = t1.
Vector3 p2 = t2.
points[i] = Waypoints[i%Waypoints.Length].
distances[i] = accumulateD
accumulateDistance += (p1 - p2).
private void OnDrawGizmos()
DrawGizmos(false);
private void OnDrawGizmosSelected()
DrawGizmos(true);
private void DrawGizmos(bool selected)
waypointList.circuit =
if (Waypoints.Length & 1)
numPoints = Waypoints.L
CachePositionsAndDistances();
Length = distances[distances.Length - 1];
Gizmos.color = selected ? Color.yellow : new Color(1, 1, 0, 0.5f);
Vector3 prev = Waypoints[0].
if (smoothRoute)
for (float dist = 0; dist & L dist += Length/editorVisualisationSubsteps)
Vector3 next = GetRoutePosition(dist + 1);
Gizmos.DrawLine(prev, next);
Gizmos.DrawLine(prev, Waypoints[0].position);
for (int n = 0; n & Waypoints.L ++n)
Vector3 next = Waypoints[(n + 1)%Waypoints.Length].
Gizmos.DrawLine(prev, next);
[Serializable]
public class WaypointList
public WaypointC
public Transform[] items = new Transform[0];
public struct RoutePoint
public Vector3
public Vector3
public RoutePoint(Vector3 position, Vector3 direction)
this.position =
this.direction =
namespace UnityStandardAssets.Utility.Inspector
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof (WaypointCircuit.WaypointList))]
public class WaypointListDrawer : PropertyDrawer
private float lineHeight = 18;
private float spacing = 4;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
EditorGUI.BeginProperty(position, label, property);
float x = position.x;
float y = position.y;
float inspectorWidth = position.
// Draw label
// Don't make child fields be indented
var indent = EditorGUI.indentL
EditorGUI.indentLevel = 0;
var items = property.FindPropertyRelative(&items&);
var titles = new string[] {&Transform&, &&, &&, &&};
var props = new string[] {&transform&, &^&, &v&, &-&};
var widths = new float[] {.7f, .1f, .1f, .1f};
float lineHeight = 18;
bool changedLength =
if (items.arraySize & 0)
for (int i = -1; i & items.arrayS ++i)
var item = items.GetArrayElementAtIndex(i);
float rowX =
for (int n = 0; n & props.L ++n)
float w = widths[n]*inspectorW
// Calculate rects
Rect rect = new Rect(rowX, y, w, lineHeight);
if (i == -1)
EditorGUI.LabelField(rect, titles[n]);
if (n == 0)
EditorGUI.ObjectField(rect, item.objectReferenceValue, typeof (Transform), true);
if (GUI.Button(rect, props[n]))
switch (props[n])
items.DeleteArrayElementAtIndex(i);
items.DeleteArrayElementAtIndex(i);
changedLength =
if (i & 0)
items.MoveArrayElement(i, i + 1);
if (i & items.arraySize - 1)
items.MoveArrayElement(i, i - 1);
y += lineHeight +
if (changedLength)
// add button
var addButtonRect = new Rect((x + position.width) - widths[widths.Length - 1]*inspectorWidth, y,
widths[widths.Length - 1]*inspectorWidth, lineHeight);
if (GUI.Button(addButtonRect, &+&))
items.InsertArrayElementAtIndex(items.arraySize);
y += lineHeight +
// add all button
var addAllButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(addAllButtonRect, &Assign using all child objects&))
var circuit = property.FindPropertyRelative(&circuit&).objectReferenceValue as WaypointC
var children = new Transform[circuit.transform.childCount];
int n = 0;
foreach (Transform child in circuit.transform)
children[n++] =
Array.Sort(children, new TransformNameComparer());
circuit.waypointList.items = new Transform[children.Length];
for (n = 0; n & children.L ++n)
circuit.waypointList.items[n] = children[n];
y += lineHeight +
// rename all button
var renameButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(renameButtonRect, &Auto Rename numerically from this order&))
var circuit = property.FindPropertyRelative(&circuit&).objectReferenceValue as WaypointC
int n = 0;
foreach (Transform child in circuit.waypointList.items)
child.name = &Waypoint & + (n++).ToString(&000&);
y += lineHeight +
// Set indent back to what it was
EditorGUI.indentLevel =
EditorGUI.EndProperty();
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
SerializedProperty items = property.FindPropertyRelative(&items&);
float lineAndSpace = lineHeight +
return 40 + (items.arraySize*lineAndSpace) + lineAndS
// comparer for check distances in ray cast hits
public class TransformNameComparer : IComparer
public int Compare(object x, object y)
return ((Transform) x).pareTo(((Transform) y).name);
using UnityE
namespace UnityStandardAssets.Utility
public class WaypointProgressTracker : MonoBehaviour
// This script can be used with any object that is supposed to follow a
// route marked out by waypoints.
// This script manages the amount to look ahead along the route,
// and keeps track of progress and laps.
[SerializeField] private WaypointC // A reference to the waypoint-based route we should follow
[SerializeField] private float lookAheadForTargetOffset = 5;
// The offset ahead along the route that the we will aim for
[SerializeField] private float lookAheadForTargetFactor = .1f;
// A multiplier adding distance ahead along the route to aim for, based on current speed
[SerializeField] private float lookAheadForSpeedOffset = 10;
// The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)
[SerializeField] private float lookAheadForSpeedFactor = .2f;
// A multiplier adding distance ahead along the route for speed adjustments
[SerializeField] private ProgressStyle progressStyle = ProgressStyle.SmoothAlongR
// whether to
the position smoothly along the route (good for curved paths) or just when we reach each waypoint.
[SerializeField] private float pointToPointThreshold = 4;
// proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.
public enum ProgressStyle
SmoothAlongRoute,
PointToPoint,
// these are public, readable by other objects - i.e. for an AI to know where to head!
public WaypointCircuit.RoutePoint targetPoint { }
public WaypointCircuit.RoutePoint speedPoint { }
public WaypointCircuit.RoutePoint progressPoint { }
private float progressD // The progress round the route, used in smooth mode.
private int progressN // the current waypoint number, used in point-to-point mode.
private Vector3 lastP // Used to calculate current speed (since we may not have a rigidbody component)
// current speed of this object (calculated from delta since last frame)
// setup script properties
private void Start()
// we use a transform to represent the point to aim for, and the point which
// is considered for upcoming changes-of-speed. This allows this component
// to communicate this information to the AI without requiring further dependencies.
// You can manually create a transform and assign it to this component *and* the AI,
// then this component will update it, and the AI can read it.
if (target == null)
target = new GameObject(name + & Waypoint Target&).
// reset the object to sensible values
public void Reset()
progressDistance = 0;
progressNum = 0;
if (progressStyle == ProgressStyle.PointToPoint)
target.position = circuit.Waypoints[progressNum].
target.rotation = circuit.Waypoints[progressNum].
private void Update()
if (progressStyle == ProgressStyle.SmoothAlongRoute)
// determine the position we should currently be aiming for
// (this is different to the current progress position, it is a a certain amount ahead along the route)
// we use lerp as a simple way of smoothing out the speed over time.
if (Time.deltaTime & 0)
speed = Mathf.Lerp(speed, (lastPosition - transform.position).magnitude/Time.deltaTime,
Time.deltaTime);
target.position =
circuit.GetRoutePoint(progressDistance + lookAheadForTargetOffset + lookAheadForTargetFactor*speed)
target.rotation =
Quaternion.LookRotation(
circuit.GetRoutePoint(progressDistance + lookAheadForSpeedOffset + lookAheadForSpeedFactor*speed)
.direction);
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.
if (Vector3.Dot(progressDelta, progressPoint.direction) & 0)
progressDistance += progressDelta.magnitude*0.5f;
lastPosition = transform.
// point to point mode. Just increase the waypoint if we're close enough:
Vector3 targetDelta = target.position - transform.
if (targetDelta.magnitude & pointToPointThreshold)
progressNum = (progressNum + 1)%circuit.Waypoints.L
target.position = circuit.Waypoints[progressNum].
target.rotation = circuit.Waypoints[progressNum].
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.
if (Vector3.Dot(progressDelta, progressPoint.direction) & 0)
progressDistance += progressDelta.
lastPosition = transform.
private void OnDrawGizmos()
if (Application.isPlaying)
Gizmos.color = Color.
Gizmos.DrawLine(transform.position, target.position);
Gizmos.DrawWireSphere(circuit.GetRoutePosition(progressDistance), 1);
Gizmos.color = Color.
Gizmos.DrawLine(target.position, target.position + target.forward);
最后: 看看Unity5的 sample中的 Car 和 飞机 的AI案例中:????
版权声明:本文为博主原创,未经博主允许不得转载。