Unity NavMesh动态烘培和绘制

来源:互联网 发布:ubuntu 卸载wineqq 编辑:程序博客网 时间:2024/05/01 05:35

前提:随着Unity5.6的推出,我们终于迎来了NavMesh的动态烘培,我们期待已久的功能终于来了,不用再研究A*算法了,话说改进的网格寻路更加方便高效。

Unity5.6 更新概要(中文版):http://mt.sohu.com/it/d20170401/131548770_280780.shtml

Unity5.6更新概要(英文版):https://blogs.unity3d.com/cn/2017/03/31/5-6-is-now-available-and-completes-the-unity-5-cycle/?_ga=1.14498615.1252386216.1491371601

下面就直接进入正题:

首先场景中的物体都要挂上这个脚本NavMeshSourceTag.cs

[csharp] view plain copy
  1. using UnityEngine;  
  2. using UnityEngine.AI;  
  3. using System.Collections.Generic;  
  4.   
  5. // Tagging component for use with the LocalNavMeshBuilder  
  6. // Supports mesh-filter and terrain - can be extended to physics and/or primitives  
  7. [DefaultExecutionOrder(-200)]  
  8. public class NavMeshSourceTag : MonoBehaviour  
  9. {  
  10.     // Global containers for all active mesh/terrain tags  
  11.     public static List<MeshFilter> m_Meshes = new List<MeshFilter>();  
  12.     public static List<Terrain> m_Terrains = new List<Terrain>();  
  13.   
  14.     void OnEnable()  
  15.     {  
  16.         var m = GetComponent<MeshFilter>();  
  17.         if (m != null)  
  18.         {  
  19.             m_Meshes.Add(m);  
  20.         }  
  21.   
  22.         var t = GetComponent<Terrain>();  
  23.         if (t != null)  
  24.         {  
  25.             m_Terrains.Add(t);  
  26.         }  
  27.     }  
  28.   
  29.     void OnDisable()  
  30.     {  
  31.         var m = GetComponent<MeshFilter>();  
  32.         if (m != null)  
  33.         {  
  34.             m_Meshes.Remove(m);  
  35.         }  
  36.   
  37.         var t = GetComponent<Terrain>();  
  38.         if (t != null)  
  39.         {  
  40.             m_Terrains.Remove(t);  
  41.         }  
  42.     }  
  43.   
  44.     // Collect all the navmesh build sources for enabled objects tagged by this component  
  45.     public static void Collect(ref List<NavMeshBuildSource> sources)  
  46.     {  
  47.         sources.Clear();  
  48.   
  49.         for (var i = 0; i < m_Meshes.Count; ++i)  
  50.         {  
  51.             var mf = m_Meshes[i];  
  52.             if (mf == nullcontinue;  
  53.   
  54.             var m = mf.sharedMesh;  
  55.             if (m == nullcontinue;  
  56.   
  57.             var s = new NavMeshBuildSource();  
  58.             s.shape = NavMeshBuildSourceShape.Mesh;  
  59.             s.sourceObject = m;  
  60.             s.transform = mf.transform.localToWorldMatrix;  
  61.             s.area = 0;  
  62.             sources.Add(s);  
  63.         }  
  64.   
  65.         for (var i = 0; i < m_Terrains.Count; ++i)  
  66.         {  
  67.             var t = m_Terrains[i];  
  68.             if (t == nullcontinue;  
  69.   
  70.             var s = new NavMeshBuildSource();  
  71.             s.shape = NavMeshBuildSourceShape.Terrain;  
  72.             s.sourceObject = t.terrainData;  
  73.             // Terrain system only supports translation - so we pass translation only to back-end  
  74.             s.transform = Matrix4x4.TRS(t.transform.position, Quaternion.identity, Vector3.one);  
  75.             s.area = 0;  
  76.             sources.Add(s);  
  77.         }  
  78.     }  
  79. }  

然后新建个空物体挂上脚本:My_LocalNavMeshBuilder.cs,我这里修改了下,就刷新一次,所以m_Size要框住场景,再加上Msh 和MeshFilter,这是用来绘制NavMesh的。

[csharp] view plain copy
  1. using UnityEngine;  
  2. using UnityEngine.AI;  
  3. using System.Collections;  
  4. using System.Collections.Generic;  
  5. using NavMeshBuilder = UnityEngine.AI.NavMeshBuilder;  
  6.   
  7. // Build and update a localized navmesh from the sources marked by NavMeshSourceTag  
  8. [DefaultExecutionOrder(-102)]  
  9. public class My_LocalNavMeshBuilder : MonoBehaviour  
  10. {  
  11.     // The center of the build  
  12.     public Transform m_Tracked;  
  13.   
  14.     // The size of the build bounds  
  15.     public Vector3 m_Size = new Vector3(80.0f, 20.0f, 80.0f);  
  16.   
  17.     NavMeshData m_NavMesh;  
  18.     AsyncOperation m_Operation;  
  19.     NavMeshDataInstance m_Instance;  
  20.     List<NavMeshBuildSource> m_Sources = new List<NavMeshBuildSource>();  
  21.   
  22.     private MeshFilter mf;  
  23.     private Mesh m;  
  24.   
  25.     //IEnumerator Start()  
  26.     //{  
  27.     //    while (true)  
  28.     //    {  
  29.     //        UpdateNavMesh(true);  
  30.     //        yield return m_Operation;  
  31.     //    }  
  32.     //}  
  33.   
  34.     void Start()  
  35.     {  
  36.         mf = GetComponent<MeshFilter>();  
  37.         m = mf.mesh;  
  38.     }  
  39.   
  40.     void Update()  
  41.     {  
  42.         if(Input.GetKey(KeyCode.A))  
  43.         {  
  44.             bake();  
  45.         }  
  46.   
  47.         if(Input.GetKey(KeyCode.D))  
  48.         {  
  49.             drawNavMesh();  
  50.         }  
  51.     }  
  52.   
  53.     private void bake()  
  54.     {  
  55.         m_NavMesh = new NavMeshData();  
  56.         m_Instance = NavMesh.AddNavMeshData(m_NavMesh);  
  57.         if (m_Tracked == null)  
  58.             m_Tracked = transform;  
  59.         UpdateNavMesh(false);  
  60.     }  
  61.   
  62.     private void drawNavMesh()  
  63.     {  
  64.         NavMeshTriangulation nt = NavMesh.CalculateTriangulation();  
  65.         m.vertices = nt.vertices;  
  66.         m.triangles = nt.indices;  
  67.     }  
  68.   
  69.     //void OnEnable()  
  70.     //{  
  71.     //    // Construct and add navmesh  
  72.     //    m_NavMesh = new NavMeshData();  
  73.     //    m_Instance = NavMesh.AddNavMeshData(m_NavMesh);  
  74.     //    if (m_Tracked == null)  
  75.     //        m_Tracked = transform;  
  76.     //    UpdateNavMesh(false);  
  77.     //}  
  78.   
  79.     //void OnDisable()  
  80.     //{  
  81.     //    // Unload navmesh and clear handle  
  82.     //    m_Instance.Remove();  
  83.     //}  
  84.   
  85.     void UpdateNavMesh(bool asyncUpdate = false)  
  86.     {  
  87.         NavMeshSourceTag.Collect(ref m_Sources);  
  88.         var defaultBuildSettings = NavMesh.GetSettingsByID(0);  
  89.         var bounds = QuantizedBounds();  
  90.   
  91.         if (asyncUpdate)  
  92.             m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);  
  93.         else  
  94.             NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);  
  95.     }  
  96.   
  97.     static Vector3 Quantize(Vector3 v, Vector3 quant)  
  98.     {  
  99.         float x = quant.x * Mathf.Floor(v.x / quant.x);  
  100.         float y = quant.y * Mathf.Floor(v.y / quant.y);  
  101.         float z = quant.z * Mathf.Floor(v.z / quant.z);  
  102.         return new Vector3(x, y, z);  
  103.     }  
  104.   
  105.     Bounds QuantizedBounds()  
  106.     {  
  107.         // Quantize the bounds to update only when theres a 10% change in size  
  108.         var center = m_Tracked ? m_Tracked.position : transform.position;  
  109.         return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);  
  110.     }  
  111.   
  112.     void OnDrawGizmosSelected()  
  113.     {  
  114.         if (m_NavMesh)  
  115.         {  
  116.             Gizmos.color = Color.green;  
  117.             Gizmos.DrawWireCube(m_NavMesh.sourceBounds.center, m_NavMesh.sourceBounds.size);  
  118.         }  
  119.   
  120.         Gizmos.color = Color.yellow;  
  121.         var bounds = QuantizedBounds();  
  122.         Gizmos.DrawWireCube(bounds.center, bounds.size);  
  123.   
  124.         Gizmos.color = Color.green;  
  125.         var center = m_Tracked ? m_Tracked.position : transform.position;  
  126.         Gizmos.DrawWireCube(center, m_Size);  
  127.     }  
  128. }  

最后再在你的人物上面加上NavMeshAgent组件,就可以控制人物寻路了。
原创粉丝点击