放置NPC
我们先在SceneMainCity放上NPC的prefab,然后在NPC的前方放上定位点,这个定位点就是Player导航的时候和NPC对话的站位。
然后在场景中放一个MapRoot对象,在上面挂载MainCityMap
脚本,并打上“MapRoot”标签,这个脚本用来记录各个定位点的位置。

1 2 3 4 5 6 7 8 9
| using UnityEngine;
namespace DarknessWarGodLearning { public class MainCityMap : MonoBehaviour { public Transform[] NpcPosTrans; } }
|
读取MapRoot内的数据
在MainCitySys
中获取进入主城的位置信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private Transform[] npcPosTrans;
public void EnterMainCity() { resSvc.AsyncLoadScene(mapData.sceneName, () => {
GameObject map = GameObject.FindGameObjectWithTag("MapRoot"); MainCityMap mainCityMap = map.GetComponent<MainCityMap>(); npcPosTrans = mainCityMap.NpcPosTrans;
}); }
|
导航网格的设置
Unity的Navigation完全是依靠标记为static的物体的Mesh Renderer内部的Mesh生成的,在烘焙导航网格时,我们需要先关闭整个场景的物体,然后再打开场景的碰撞盒,并且打开碰撞盒的Mesh,用碰撞盒的Mesh来烘焙导航网格。
烘焙好后,我们给Player的Prefab添加上Nav Mesh Agent组件,并将Angular Speed设为360。关闭掉Nav Mesh Agent组件,我们希望在点击Guide按钮的时候再开启Nav Mesh Agent
在MainCitySys
中拿到Nav Mesh Agent组件:
1 2 3 4 5 6 7 8 9 10
| private NavMeshAgent nav;
private void LoadPlayer(MapCfg mapData) { GameObject player = resSvc.LoadPrefab(PathDefine.AssassinCityPlayerPrefab,true);
nav = player.GetComponent<NavMeshAgent>(); }
|
进行任务导航,在MainCitySys
里面添加RunTask
方法
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
| private AutoGuideCfg curTaskData; private bool isNaviguiding = false;
private bool isNaviguiding = false;
public void SetMoveDir(Vector2 dir) { StopNavTask(); }
public void OpenInfoWnd() { StopNavTask(); }
public void RunTask(AutoGuideCfg autoGuideCfg) { if(autoGuideCfg != null) { curTaskData = autoGuideCfg; } nav.enabled = true; if (curTaskData.npcID != -1) { float dis = Vector3.Distance(playerController.transform.position, npcPosTrans[autoGuideCfg.npcID].position); if(dis < 0.5f) { isNaviguiding = false; nav.isStopped = true; playerController.SetAnimTreeBlend(Constants.BlendIdle); nav.enabled = false;
OpenGuideWnd(); } else { isNaviguiding=true; nav.enabled = true; nav.speed = Constants.PlayerMoveSpeed; nav.SetDestination(npcPosTrans[autoGuideCfg.npcID].position); playerController.SetAnimTreeBlend(Constants.BlendWalk); } } else { OpenGuideWnd(); } } private void StopNavTask() { if (isNaviguiding) { isNaviguiding = false; nav.isStopped = true; playerController.SetAnimTreeBlend(Constants.BlendIdle); nav.enabled = false; } } private void IsArrivedNavPos() { float dis = Vector3.Distance(playerController.transform.position, npcPosTrans[curTaskData.npcID].position); if (dis < 0.5f) { isNaviguiding = false; nav.isStopped = true; playerController.SetAnimTreeBlend(Constants.BlendIdle); nav.enabled = false;
OpenGuideWnd(); } } private void OpenGuideWnd() { } private void Update() { if (isNaviguiding) { playerController.SetCam(); IsArrivedNavPos(); } }
|