前言
为了准备老师的课设作业,我决定做一个RPG小游戏,在处理寻路的时候遇到了点小麻烦。
首先是解决方案的选取,Unity自带的Navgation Mesh挺强大的(至少在客户端是这样,hh),我之前一直用的A*
,但是不知道为什么老版本的A*
在Unity 2019.3的InspectorGUI是坏掉的。。。又没钱买正版。。。
emmm,勉为其难的选择Navgation Mesh吧。
但是Navgation Mesh好像只有带有加速度的移动方式,这就有点蛋疼,说实话我个人挺不喜欢那种手感的,所以查了查官方文档,发现了NavMeshPath这么个东西,用它就可以得到我们一次寻路过程中所有的转折点,从而自己处理寻路,那么,我们开始吧。
思路
通过调用NavMeshAgent的CalculatePath来得到NavMeshPath,并使用NavMeshPath的corners数组(记录了每一处拐点的位置)和Transform.Translate做匀速运动,人物方向的改变需要自己处理
。
代码
重要部分已注释,核心就是RunToTarget函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| namespace ETModel { [ObjectSystem] public class NavComponentAwakeSystem : AwakeSystem<NavComponent> { public override void Awake(NavComponent self) { self.NavMeshAgent = self.Entity.GameObject.AddComponent<NavMeshAgent>(); self.UserInputComponent = Game.Scene.GetComponent<UserInputComponent>(); self.CameraComponent = Game.Scene.GetComponent<CameraComponent>(); self.Transform = self.Entity.GameObject.transform; } }
[ObjectSystem] public class NavComponentUpdateSystem : UpdateSystem<NavComponent> { public override void Update(NavComponent self) { self.Update(); } }
public class NavComponent : Component { public NavMeshAgent NavMeshAgent;
public UserInputComponent UserInputComponent;
public CameraComponent CameraComponent;
private Ray m_Ray;
public Transform Transform; private NavMeshPath m_NavMeshPath = new NavMeshPath();
private int m_PreviousPathPointIndex = 0; private int m_CurrentPathPointIndex = 1;
public void RunToTarget() { if (m_CurrentPathPointIndex > m_NavMeshPath.corners.Length - 1) return;
if ((Transform.position - m_NavMeshPath.corners[m_CurrentPathPointIndex]).magnitude <= 0.1f) { m_PreviousPathPointIndex++; m_CurrentPathPointIndex++; if (m_CurrentPathPointIndex > m_NavMeshPath.corners.Length - 1) { Entity.GetComponent<StackFsmComponent>().AddState(StateTypes.Idle, "Idle", 1); return; }
Entity.GetComponent<TurnComponent>().Turn(m_NavMeshPath.corners[m_CurrentPathPointIndex]); }
Transform.Translate( ((-m_NavMeshPath.corners[m_PreviousPathPointIndex] + m_NavMeshPath.corners[m_CurrentPathPointIndex]).normalized) * (Time.deltaTime * 8.0f), Space.World); }
public override void Dispose() { if (IsDisposed) { return; }
base.Dispose(); NavMeshAgent = null; UserInputComponent = null; UnityEngine.Object.Destroy(Entity.GameObject.GetComponent<NavMeshAgent>()); }
public void Update() { if (UserInputComponent.RightMouseDown) { m_Ray = CameraComponent.mainCamera.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(m_Ray, out var hit, 2000)) { NavMeshAgent.CalculatePath(hit.point, m_NavMeshPath); m_PreviousPathPointIndex = 0; m_CurrentPathPointIndex = 1; Entity.GetComponent<TurnComponent>().Turn(m_NavMeshPath.corners[1]); Entity.GetComponent<StackFsmComponent>().AddState(StateTypes.Run, "Run", 1); } }
RunToTarget(); } } }
|
效果演示