Unity NavMesh动态烘培和绘制

来源:互联网 发布:Linux下配置gnu 编辑:程序博客网 时间:2024/05/01 17:28

前提:随着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

using UnityEngine;using UnityEngine.AI;using System.Collections.Generic;// Tagging component for use with the LocalNavMeshBuilder// Supports mesh-filter and terrain - can be extended to physics and/or primitives[DefaultExecutionOrder(-200)]public class NavMeshSourceTag : MonoBehaviour{    // Global containers for all active mesh/terrain tags    public static List<MeshFilter> m_Meshes = new List<MeshFilter>();    public static List<Terrain> m_Terrains = new List<Terrain>();    void OnEnable()    {        var m = GetComponent<MeshFilter>();        if (m != null)        {            m_Meshes.Add(m);        }        var t = GetComponent<Terrain>();        if (t != null)        {            m_Terrains.Add(t);        }    }    void OnDisable()    {        var m = GetComponent<MeshFilter>();        if (m != null)        {            m_Meshes.Remove(m);        }        var t = GetComponent<Terrain>();        if (t != null)        {            m_Terrains.Remove(t);        }    }    // Collect all the navmesh build sources for enabled objects tagged by this component    public static void Collect(ref List<NavMeshBuildSource> sources)    {        sources.Clear();        for (var i = 0; i < m_Meshes.Count; ++i)        {            var mf = m_Meshes[i];            if (mf == null) continue;            var m = mf.sharedMesh;            if (m == null) continue;            var s = new NavMeshBuildSource();            s.shape = NavMeshBuildSourceShape.Mesh;            s.sourceObject = m;            s.transform = mf.transform.localToWorldMatrix;            s.area = 0;            sources.Add(s);        }        for (var i = 0; i < m_Terrains.Count; ++i)        {            var t = m_Terrains[i];            if (t == null) continue;            var s = new NavMeshBuildSource();            s.shape = NavMeshBuildSourceShape.Terrain;            s.sourceObject = t.terrainData;            // Terrain system only supports translation - so we pass translation only to back-end            s.transform = Matrix4x4.TRS(t.transform.position, Quaternion.identity, Vector3.one);            s.area = 0;            sources.Add(s);        }    }}

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

using UnityEngine;using UnityEngine.AI;using System.Collections;using System.Collections.Generic;using NavMeshBuilder = UnityEngine.AI.NavMeshBuilder;// Build and update a localized navmesh from the sources marked by NavMeshSourceTag[DefaultExecutionOrder(-102)]public class My_LocalNavMeshBuilder : MonoBehaviour{    // The center of the build    public Transform m_Tracked;    // The size of the build bounds    public Vector3 m_Size = new Vector3(80.0f, 20.0f, 80.0f);    NavMeshData m_NavMesh;    AsyncOperation m_Operation;    NavMeshDataInstance m_Instance;    List<NavMeshBuildSource> m_Sources = new List<NavMeshBuildSource>();    private MeshFilter mf;    private Mesh m;    //IEnumerator Start()    //{    //    while (true)    //    {    //        UpdateNavMesh(true);    //        yield return m_Operation;    //    }    //}    void Start()    {        mf = GetComponent<MeshFilter>();        m = mf.mesh;    }    void Update()    {        if(Input.GetKey(KeyCode.A))        {            bake();        }        if(Input.GetKey(KeyCode.D))        {            drawNavMesh();        }    }    private void bake()    {        m_NavMesh = new NavMeshData();        m_Instance = NavMesh.AddNavMeshData(m_NavMesh);        if (m_Tracked == null)            m_Tracked = transform;        UpdateNavMesh(false);    }    private void drawNavMesh()    {        NavMeshTriangulation nt = NavMesh.CalculateTriangulation();        m.vertices = nt.vertices;        m.triangles = nt.indices;    }    //void OnEnable()    //{    //    // Construct and add navmesh    //    m_NavMesh = new NavMeshData();    //    m_Instance = NavMesh.AddNavMeshData(m_NavMesh);    //    if (m_Tracked == null)    //        m_Tracked = transform;    //    UpdateNavMesh(false);    //}    //void OnDisable()    //{    //    // Unload navmesh and clear handle    //    m_Instance.Remove();    //}    void UpdateNavMesh(bool asyncUpdate = false)    {        NavMeshSourceTag.Collect(ref m_Sources);        var defaultBuildSettings = NavMesh.GetSettingsByID(0);        var bounds = QuantizedBounds();        if (asyncUpdate)            m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);        else            NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);    }    static Vector3 Quantize(Vector3 v, Vector3 quant)    {        float x = quant.x * Mathf.Floor(v.x / quant.x);        float y = quant.y * Mathf.Floor(v.y / quant.y);        float z = quant.z * Mathf.Floor(v.z / quant.z);        return new Vector3(x, y, z);    }    Bounds QuantizedBounds()    {        // Quantize the bounds to update only when theres a 10% change in size        var center = m_Tracked ? m_Tracked.position : transform.position;        return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);    }    void OnDrawGizmosSelected()    {        if (m_NavMesh)        {            Gizmos.color = Color.green;            Gizmos.DrawWireCube(m_NavMesh.sourceBounds.center, m_NavMesh.sourceBounds.size);        }        Gizmos.color = Color.yellow;        var bounds = QuantizedBounds();        Gizmos.DrawWireCube(bounds.center, bounds.size);        Gizmos.color = Color.green;        var center = m_Tracked ? m_Tracked.position : transform.position;        Gizmos.DrawWireCube(center, m_Size);    }}

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

最后附上工程文件,象征性的收取点手续费,点击下载

1 0
原创粉丝点击