NavMeshComponents插件(NavMeshPrefabInstance)----------预制体绑定NavMeshDate(unity2018.3)

7 篇文章 0 订阅

Demo:https://download.csdn.net/download/fireworksflower/11594547
如果你去查找资料,可以找到一堆关于NavMeshComponents的内容(都是一些5.4左右版本),但是对于NavMeshPrefabInstance(unity2018)几乎没有(本人找到了官方的但是都是英文,而且很麻烦)所以,我就自己找问题。
1.想要将预制体和NavMeshDate绑定在一起肯定少不了NavMeshPrefabInstance.cs脚本。
在这里插入图片描述

在这里插入图片描述
就自己修改了一下代码:
1.找到脚本NavMeshPrefabInstanceEditor.cs
源码是这样的:

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;

[CanEditMultipleObjects]
[CustomEditor(typeof(NavMeshPrefabInstance))]
class NavMeshPrefabInstanceEditor : Editor
{
SerializedProperty m_FollowTransformProp;
SerializedProperty m_NavMeshDataProp;

public void OnEnable()
{
    m_FollowTransformProp = serializedObject.FindProperty("m_FollowTransform");
    m_NavMeshDataProp = serializedObject.FindProperty("m_NavMesh");
}

public override void OnInspectorGUI()
{
    var instance = (NavMeshPrefabInstance)target;
    var go = instance.gameObject;

    serializedObject.Update();

    GUI.enabled = false;
    EditorGUILayout.PropertyField(m_NavMeshDataProp);
    GUI.enabled = true;
    EditorGUILayout.PropertyField(m_FollowTransformProp);

    EditorGUILayout.Space();

    OnInspectorGUIPrefab(go);

    serializedObject.ApplyModifiedProperties();
}

void OnInspectorGUIPrefab(GameObject go)
{
    var prefab = PrefabUtility.GetPrefabInstanceHandle(go);
    var path = AssetDatabase.GetAssetPath(prefab);

    if (prefab && string.IsNullOrEmpty(path))
    {
        if (GUILayout.Button("Select the Prefab asset to bake or clear the navmesh", EditorStyles.helpBox))
        {
            Selection.activeObject = PrefabUtility.GetCorrespondingObjectFromSource(go);
            EditorGUIUtility.PingObject(Selection.activeObject);
        }
    }

    if (string.IsNullOrEmpty(path))
        return;

    GUILayout.BeginHorizontal();
    GUILayout.Space(EditorGUIUtility.labelWidth);

    if (GUILayout.Button("Clear"))
        OnClear();

    if (GUILayout.Button("Bake"))
        OnBake();

    GUILayout.EndHorizontal();
}

NavMeshData Build(NavMeshPrefabInstance instance)
{
    var root = instance.transform;
    var sources = new List<NavMeshBuildSource>();
    var markups = new List<NavMeshBuildMarkup>();

    UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
        root, ~0, NavMeshCollectGeometry.RenderMeshes, 0, markups, instance.gameObject.scene, sources);
    var settings = NavMesh.GetSettingsByID(0);
    var bounds = new Bounds(Vector3.zero, 1000.0f * Vector3.one);
    var navmesh = NavMeshBuilder.BuildNavMeshData(settings, sources, bounds, root.position, root.rotation);
    navmesh.name = "Navmesh";
    return navmesh;
}

void OnClear()
{
    foreach (var tgt in targets)
    {
        var instance = (NavMeshPrefabInstance)tgt;
        var go = instance.gameObject;
        var prefab = PrefabUtility.GetPrefabInstanceHandle(go);
        var path = AssetDatabase.GetAssetPath(prefab);

        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("GameObject: " + go + " has no valid prefab path");
            continue;
        }

        DestroyNavMeshData(path);
        AssetDatabase.SaveAssets();
    }
}

void OnBake()
{
    foreach (var tgt in targets)
    {
        var instance = (NavMeshPrefabInstance)tgt;
        var go = instance.gameObject;
        var prefab = PrefabUtility.GetPrefabInstanceHandle(go);
        var path = AssetDatabase.GetAssetPath(prefab);

        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("GameObject: " + go + " has no valid prefab path");
            continue;
        }

        DestroyNavMeshData(path);

        // Store navmesh as a sub-asset of the prefab
        var navmesh = Build(instance);
        AssetDatabase.AddObjectToAsset(navmesh, prefab);

        instance.navMeshData = navmesh;
        AssetDatabase.SaveAssets();
    }
}

void DestroyNavMeshData(string path)
{
    // Destroy and remove all existing NavMeshData sub-assets
    var assets = AssetDatabase.LoadAllAssetsAtPath(path);
    foreach (var o in assets)
    {
        var data = o as NavMeshData;
        if (data != null)
            DestroyImmediate(o, true);
    }
}

[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)]
static void RenderGizmo(NavMeshPrefabInstance instance, GizmoType gizmoType)
{
    if (!EditorApplication.isPlaying)
        instance.UpdateInstance();
}

}

修改后:

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;

[CanEditMultipleObjects]
[CustomEditor(typeof(NavMeshPrefabInstance))]
class NavMeshPrefabInstanceEditor : Editor
{
SerializedProperty m_FollowTransformProp;
SerializedProperty m_NavMeshDataProp;

public void OnEnable()
{
    m_FollowTransformProp = serializedObject.FindProperty("m_FollowTransform");
    m_NavMeshDataProp = serializedObject.FindProperty("m_NavMesh");
}

public override void OnInspectorGUI()
{
    var instance = (NavMeshPrefabInstance)target;
    var go = instance.gameObject;

    serializedObject.Update();

    GUI.enabled = true;
    EditorGUILayout.PropertyField(m_NavMeshDataProp);
    GUI.enabled = true;
    EditorGUILayout.PropertyField(m_FollowTransformProp);

    EditorGUILayout.Space();

    OnInspectorGUIPrefab(go);

    serializedObject.ApplyModifiedProperties();
}
string path = null;
void OnInspectorGUIPrefab(GameObject go)
{

    if (GUILayout.Button( "Select the Prefab asset to bake or clear the navmesh", EditorStyles.helpBox ))
    {
        var prefab = PrefabUtility.GetCorrespondingObjectFromSource( Selection.activeObject );
        path = AssetDatabase.GetAssetPath( prefab );
    }

    if (string.IsNullOrEmpty( path ))
        return;

    GUILayout.BeginHorizontal( );
    GUILayout.Space( EditorGUIUtility.labelWidth );

    if (GUILayout.Button( "Clear" ))
        OnClear( );

    if (GUILayout.Button( "Bake" ))
        OnBake( );

    GUILayout.EndHorizontal( );
}

NavMeshData Build(NavMeshPrefabInstance instance)
{
    var root = instance.transform;
    var sources = new List<NavMeshBuildSource>();
    var markups = new List<NavMeshBuildMarkup>();

    UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
        root, ~0, NavMeshCollectGeometry.PhysicsColliders, 0, markups, instance.gameObject.scene, sources);
    var settings = NavMesh.GetSettingsByID(0);
    var bounds = new Bounds(Vector3.zero, /*1000.0f * Vector3.one*/new Vector3(1000,5,1000));
    var navmesh = NavMeshBuilder.BuildNavMeshData(settings, sources, bounds, root.position, root.rotation);
    navmesh.name = "Navmesh";
    return navmesh;
}

void OnClear()
{
    foreach (var tgt in targets)
    {
        var instance = (NavMeshPrefabInstance)tgt;
        var go = instance.gameObject;
        //var prefab = PrefabUtility.GetPrefabInstanceHandle(go);
        var prefab = PrefabUtility.GetCorrespondingObjectFromSource( Selection.activeObject );
        var path = AssetDatabase.GetAssetPath(prefab);

        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("GameObject: " + go + " has no valid prefab path");
            continue;
        }

        DestroyNavMeshData(path);
        AssetDatabase.SaveAssets();
    }
}

void OnBake()
{

    for (int i = 0 ; i < targets.Length ; i++)
    {
        var instance = (NavMeshPrefabInstance)targets[i];
        var go = instance.gameObject;
        // var prefab = PrefabUtility.GetPrefabInstanceHandle( go );
        var prefab = PrefabUtility.GetCorrespondingObjectFromSource( Selection.activeObject );
        var path = AssetDatabase.GetAssetPath( prefab );

        if (string.IsNullOrEmpty( path ))
        {
            Debug.LogError( "GameObject: " + go + " has no valid prefab path" );
            continue;
        }

        DestroyNavMeshData( path );

        // Store navmesh as a sub-asset of the prefab
        var navmesh = Build( instance );
        AssetDatabase.AddObjectToAsset( navmesh, prefab );

        GameObject TagetObj = prefab as GameObject;
        TagetObj.GetComponent<NavMeshPrefabInstance>( ).navMeshData = navmesh;
        
        AssetDatabase.SaveAssets( );

    }
}

void DestroyNavMeshData(string path)
{
    // Destroy and remove all existing NavMeshData sub-assets
    var assets = AssetDatabase.LoadAllAssetsAtPath(path);
    foreach (var o in assets)
    {
        var data = o as NavMeshData;
        if (data != null)
            DestroyImmediate(o, true);
    }
}

[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)]
static void RenderGizmo(NavMeshPrefabInstance instance, GizmoType gizmoType)
{
    if (!EditorApplication.isPlaying)
        instance.UpdateInstance();
}

}

主要原因是:
在这里插入图片描述
修改后代码:
在这里插入图片描述
下面两个方法也需要修改下:
在这里插入图片描述
下面这两行代码主要是赋值的时候出现问题了:没有赋值上,所以我小小的改动了下:
在这里插入图片描述

好了问题解决了
可以看看效果了
在这里插入图片描述
在这里插入图片描述
按钮出现了,点击烘焙就可以了

在这里插入图片描述

效果已实现。
这样就可以动态加载地图了(不是动态烘焙,它是游戏开始之前就烘焙好的)。

当然你还想要设置NavMeshDate的数据这里都是代码里:
在这里插入图片描述

OK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值