André McGrail
5 年前
当前提交
8653c6cc
共有 66 个文件被更改,包括 9513 次插入 和 4777 次删除
-
4Assets/Materials/Splash.mat
-
9Assets/NavMeshComponents/Editor.meta
-
325Assets/NavMeshComponents/Editor/NavMeshAssetManager.cs
-
11Assets/NavMeshComponents/Editor/NavMeshAssetManager.cs.meta
-
6Assets/NavMeshComponents/Editor/NavMeshComponentsEditor.asmdef
-
7Assets/NavMeshComponents/Editor/NavMeshComponentsEditor.asmdef.meta
-
258Assets/NavMeshComponents/Editor/NavMeshComponentsGUIUtility.cs
-
12Assets/NavMeshComponents/Editor/NavMeshComponentsGUIUtility.cs.meta
-
279Assets/NavMeshComponents/Editor/NavMeshLinkEditor.cs
-
12Assets/NavMeshComponents/Editor/NavMeshLinkEditor.cs.meta
-
49Assets/NavMeshComponents/Editor/NavMeshModifierEditor.cs
-
12Assets/NavMeshComponents/Editor/NavMeshModifierEditor.cs.meta
-
146Assets/NavMeshComponents/Editor/NavMeshModifierVolumeEditor.cs
-
12Assets/NavMeshComponents/Editor/NavMeshModifierVolumeEditor.cs.meta
-
400Assets/NavMeshComponents/Editor/NavMeshSurfaceEditor.cs
-
12Assets/NavMeshComponents/Editor/NavMeshSurfaceEditor.cs.meta
-
9Assets/NavMeshComponents/Scripts.meta
-
6Assets/NavMeshComponents/Scripts/NavMeshComponents.asmdef
-
7Assets/NavMeshComponents/Scripts/NavMeshComponents.asmdef.meta
-
172Assets/NavMeshComponents/Scripts/NavMeshLink.cs
-
12Assets/NavMeshComponents/Scripts/NavMeshLink.cs.meta
-
54Assets/NavMeshComponents/Scripts/NavMeshModifier.cs
-
12Assets/NavMeshComponents/Scripts/NavMeshModifier.cs.meta
-
54Assets/NavMeshComponents/Scripts/NavMeshModifierVolume.cs
-
12Assets/NavMeshComponents/Scripts/NavMeshModifierVolume.cs.meta
-
486Assets/NavMeshComponents/Scripts/NavMeshSurface.cs
-
12Assets/NavMeshComponents/Scripts/NavMeshSurface.cs.meta
-
483Assets/Objects/Levels/Island/Island Level.prefab
-
158Assets/Objects/props/props/Prefabs/Windsurfer.prefab
-
2Assets/Scripts/Boat/AIcontroller.cs
-
17Assets/Scripts/Boat/BoatController.cs
-
63Assets/Scripts/GameSystem/Editor/WaypointGroupEditor.cs
-
72Assets/Scripts/GameSystem/WaypointGroup.cs
-
80Assets/Scripts/System/MiniProfiler.cs
-
38Assets/Shaders/Graphs/CliffShader.ShaderGraph
-
47Assets/Shaders/Graphs/PBR_HUE.ShaderGraph
-
4Assets/Shaders/Graphs/Vegetation.shadergraph
-
823Assets/scenes/Island.unity
-
6Assets/scenes/Island/LightingData.asset
-
3Assets/scenes/Island/Lightmap-0_comp_dir.png.meta
-
3Assets/scenes/Island/Lightmap-0_comp_light.exr.meta
-
3Assets/scenes/Island/Lightmap-1_comp_dir.png.meta
-
3Assets/scenes/Island/Lightmap-1_comp_light.exr.meta
-
983Assets/scenes/Island/MainIsland.asset
-
786Assets/scenes/Island/ReflectionProbe-0.exr
-
795Assets/scenes/Island/ReflectionProbe-1.exr
-
800Assets/scenes/Island/ReflectionProbe-2.exr
-
787Assets/scenes/Island/ReflectionProbe-3.exr
-
823Assets/scenes/Island/ReflectionProbe-4.exr
-
734Assets/scenes/Island/ReflectionProbe-5.exr
-
756Assets/scenes/Island/ReflectionProbe-6.exr
-
772Assets/scenes/Island/ReflectionProbe-7.exr
-
198Assets/scenes/MainMenu.unity
-
3Packages/com.verasl.water-system/Scripts/BuoyantObject.cs
-
86Packages/com.verasl.water-system/Shaders/WaterCaustics.shadergraph
-
1ProjectSettings/GraphicsSettings.asset
-
37ProjectSettings/ProjectSettings.asset
-
4ProjectSettings/ProjectVersion.txt
-
334Assets/Objects/Levels/Island/NavMesh-NavMesh.asset
-
8Assets/Objects/Levels/Island/NavMesh-NavMesh.asset.meta
-
40Assets/Scripts/GameSystem/RaceManager.cs
-
11Assets/Scripts/GameSystem/RaceManager.cs.meta
-
1001Assets/Textures/UI/BG.png
-
139Assets/Textures/UI/BG.png.meta
-
858Assets/Textures/UI/Logo.png
-
139Assets/Textures/UI/Logo.png.meta
|
|||
fileFormatVersion: 2 |
|||
guid: 63b588f3892bb4b5eb73ad3d2791e05c |
|||
folderAsset: yes |
|||
timeCreated: 1477656493 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using UnityEditor.Experimental.SceneManagement; |
|||
using UnityEditor.SceneManagement; |
|||
using UnityEngine.AI; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
public class NavMeshAssetManager : ScriptableSingleton<NavMeshAssetManager> |
|||
{ |
|||
internal struct AsyncBakeOperation |
|||
{ |
|||
public NavMeshSurface surface; |
|||
public NavMeshData bakeData; |
|||
public AsyncOperation bakeOperation; |
|||
} |
|||
|
|||
List<AsyncBakeOperation> m_BakeOperations = new List<AsyncBakeOperation>(); |
|||
internal List<AsyncBakeOperation> GetBakeOperations() { return m_BakeOperations; } |
|||
|
|||
struct SavedPrefabNavMeshData |
|||
{ |
|||
public NavMeshSurface surface; |
|||
public NavMeshData navMeshData; |
|||
} |
|||
|
|||
List<SavedPrefabNavMeshData> m_PrefabNavMeshDataAssets = new List<SavedPrefabNavMeshData>(); |
|||
|
|||
static string GetAndEnsureTargetPath(NavMeshSurface surface) |
|||
{ |
|||
// Create directory for the asset if it does not exist yet.
|
|||
var activeScenePath = surface.gameObject.scene.path; |
|||
|
|||
var targetPath = "Assets"; |
|||
if (!string.IsNullOrEmpty(activeScenePath)) |
|||
{ |
|||
targetPath = Path.Combine(Path.GetDirectoryName(activeScenePath), Path.GetFileNameWithoutExtension(activeScenePath)); |
|||
} |
|||
else |
|||
{ |
|||
var prefabStage = PrefabStageUtility.GetPrefabStage(surface.gameObject); |
|||
var isPartOfPrefab = prefabStage != null && prefabStage.IsPartOfPrefabContents(surface.gameObject); |
|||
if (isPartOfPrefab && !string.IsNullOrEmpty(prefabStage.prefabAssetPath)) |
|||
{ |
|||
var prefabDirectoryName = Path.GetDirectoryName(prefabStage.prefabAssetPath); |
|||
if (!string.IsNullOrEmpty(prefabDirectoryName)) |
|||
targetPath = prefabDirectoryName; |
|||
} |
|||
} |
|||
if (!Directory.Exists(targetPath)) |
|||
Directory.CreateDirectory(targetPath); |
|||
return targetPath; |
|||
} |
|||
|
|||
static void CreateNavMeshAsset(NavMeshSurface surface) |
|||
{ |
|||
var targetPath = GetAndEnsureTargetPath(surface); |
|||
|
|||
var combinedAssetPath = Path.Combine(targetPath, "NavMesh-" + surface.name + ".asset"); |
|||
combinedAssetPath = AssetDatabase.GenerateUniqueAssetPath(combinedAssetPath); |
|||
AssetDatabase.CreateAsset(surface.navMeshData, combinedAssetPath); |
|||
} |
|||
|
|||
NavMeshData GetNavMeshAssetToDelete(NavMeshSurface navSurface) |
|||
{ |
|||
if (PrefabUtility.IsPartOfPrefabInstance(navSurface) && !PrefabUtility.IsPartOfModelPrefab(navSurface)) |
|||
{ |
|||
// Don't allow deleting the asset belonging to the prefab parent
|
|||
var parentSurface = PrefabUtility.GetCorrespondingObjectFromSource(navSurface) as NavMeshSurface; |
|||
if (parentSurface && navSurface.navMeshData == parentSurface.navMeshData) |
|||
return null; |
|||
} |
|||
|
|||
// Do not delete the NavMeshData asset referenced from a prefab until the prefab is saved
|
|||
var prefabStage = PrefabStageUtility.GetPrefabStage(navSurface.gameObject); |
|||
var isPartOfPrefab = prefabStage != null && prefabStage.IsPartOfPrefabContents(navSurface.gameObject); |
|||
if (isPartOfPrefab && IsCurrentPrefabNavMeshDataStored(navSurface)) |
|||
return null; |
|||
|
|||
return navSurface.navMeshData; |
|||
} |
|||
|
|||
void ClearSurface(NavMeshSurface navSurface) |
|||
{ |
|||
var hasNavMeshData = navSurface.navMeshData != null; |
|||
StoreNavMeshDataIfInPrefab(navSurface); |
|||
|
|||
var assetToDelete = GetNavMeshAssetToDelete(navSurface); |
|||
navSurface.RemoveData(); |
|||
|
|||
if (hasNavMeshData) |
|||
{ |
|||
SetNavMeshData(navSurface, null); |
|||
EditorSceneManager.MarkSceneDirty(navSurface.gameObject.scene); |
|||
} |
|||
|
|||
if (assetToDelete) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(assetToDelete)); |
|||
} |
|||
|
|||
public void StartBakingSurfaces(UnityEngine.Object[] surfaces) |
|||
{ |
|||
// Remove first to avoid double registration of the callback
|
|||
EditorApplication.update -= UpdateAsyncBuildOperations; |
|||
EditorApplication.update += UpdateAsyncBuildOperations; |
|||
|
|||
foreach (NavMeshSurface surf in surfaces) |
|||
{ |
|||
StoreNavMeshDataIfInPrefab(surf); |
|||
|
|||
var oper = new AsyncBakeOperation(); |
|||
|
|||
oper.bakeData = InitializeBakeData(surf); |
|||
oper.bakeOperation = surf.UpdateNavMesh(oper.bakeData); |
|||
oper.surface = surf; |
|||
|
|||
m_BakeOperations.Add(oper); |
|||
} |
|||
} |
|||
|
|||
static NavMeshData InitializeBakeData(NavMeshSurface surface) |
|||
{ |
|||
var emptySources = new List<NavMeshBuildSource>(); |
|||
var emptyBounds = new Bounds(); |
|||
return UnityEngine.AI.NavMeshBuilder.BuildNavMeshData(surface.GetBuildSettings(), emptySources, emptyBounds |
|||
, surface.transform.position, surface.transform.rotation); |
|||
} |
|||
|
|||
void UpdateAsyncBuildOperations() |
|||
{ |
|||
foreach (var oper in m_BakeOperations) |
|||
{ |
|||
if (oper.surface == null || oper.bakeOperation == null) |
|||
continue; |
|||
|
|||
if (oper.bakeOperation.isDone) |
|||
{ |
|||
var surface = oper.surface; |
|||
var delete = GetNavMeshAssetToDelete(surface); |
|||
if (delete != null) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(delete)); |
|||
|
|||
surface.RemoveData(); |
|||
SetNavMeshData(surface, oper.bakeData); |
|||
|
|||
if (surface.isActiveAndEnabled) |
|||
surface.AddData(); |
|||
CreateNavMeshAsset(surface); |
|||
EditorSceneManager.MarkSceneDirty(surface.gameObject.scene); |
|||
} |
|||
} |
|||
m_BakeOperations.RemoveAll(o => o.bakeOperation == null || o.bakeOperation.isDone); |
|||
if (m_BakeOperations.Count == 0) |
|||
EditorApplication.update -= UpdateAsyncBuildOperations; |
|||
} |
|||
|
|||
public bool IsSurfaceBaking(NavMeshSurface surface) |
|||
{ |
|||
if (surface == null) |
|||
return false; |
|||
|
|||
foreach (var oper in m_BakeOperations) |
|||
{ |
|||
if (oper.surface == null || oper.bakeOperation == null) |
|||
continue; |
|||
|
|||
if (oper.surface == surface) |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public void ClearSurfaces(UnityEngine.Object[] surfaces) |
|||
{ |
|||
foreach (NavMeshSurface s in surfaces) |
|||
ClearSurface(s); |
|||
} |
|||
|
|||
static void SetNavMeshData(NavMeshSurface navSurface, NavMeshData navMeshData) |
|||
{ |
|||
var so = new SerializedObject(navSurface); |
|||
var navMeshDataProperty = so.FindProperty("m_NavMeshData"); |
|||
navMeshDataProperty.objectReferenceValue = navMeshData; |
|||
so.ApplyModifiedPropertiesWithoutUndo(); |
|||
} |
|||
|
|||
void StoreNavMeshDataIfInPrefab(NavMeshSurface surfaceToStore) |
|||
{ |
|||
var prefabStage = PrefabStageUtility.GetPrefabStage(surfaceToStore.gameObject); |
|||
var isPartOfPrefab = prefabStage != null && prefabStage.IsPartOfPrefabContents(surfaceToStore.gameObject); |
|||
if (!isPartOfPrefab) |
|||
return; |
|||
|
|||
// check if data has already been stored for this surface
|
|||
foreach (var storedAssetInfo in m_PrefabNavMeshDataAssets) |
|||
if (storedAssetInfo.surface == surfaceToStore) |
|||
return; |
|||
|
|||
if (m_PrefabNavMeshDataAssets.Count == 0) |
|||
{ |
|||
PrefabStage.prefabSaving -= DeleteStoredNavMeshDataAssetsForOwnedSurfaces; |
|||
PrefabStage.prefabSaving += DeleteStoredNavMeshDataAssetsForOwnedSurfaces; |
|||
|
|||
PrefabStage.prefabStageClosing -= ForgetUnsavedNavMeshDataChanges; |
|||
PrefabStage.prefabStageClosing += ForgetUnsavedNavMeshDataChanges; |
|||
} |
|||
|
|||
var isDataOwner = true; |
|||
if (PrefabUtility.IsPartOfPrefabInstance(surfaceToStore) && !PrefabUtility.IsPartOfModelPrefab(surfaceToStore)) |
|||
{ |
|||
var basePrefabSurface = PrefabUtility.GetCorrespondingObjectFromSource(surfaceToStore) as NavMeshSurface; |
|||
isDataOwner = basePrefabSurface == null || surfaceToStore.navMeshData != basePrefabSurface.navMeshData; |
|||
} |
|||
m_PrefabNavMeshDataAssets.Add(new SavedPrefabNavMeshData { surface = surfaceToStore, navMeshData = isDataOwner ? surfaceToStore.navMeshData : null }); |
|||
} |
|||
|
|||
bool IsCurrentPrefabNavMeshDataStored(NavMeshSurface surface) |
|||
{ |
|||
if (surface == null) |
|||
return false; |
|||
|
|||
foreach (var storedAssetInfo in m_PrefabNavMeshDataAssets) |
|||
{ |
|||
if (storedAssetInfo.surface == surface) |
|||
return storedAssetInfo.navMeshData == surface.navMeshData; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void DeleteStoredNavMeshDataAssetsForOwnedSurfaces(GameObject gameObjectInPrefab) |
|||
{ |
|||
// Debug.LogFormat("DeleteStoredNavMeshDataAsset() when saving prefab {0}", gameObjectInPrefab.name);
|
|||
|
|||
var surfaces = gameObjectInPrefab.GetComponentsInChildren<NavMeshSurface>(true); |
|||
foreach (var surface in surfaces) |
|||
DeleteStoredPrefabNavMeshDataAsset(surface); |
|||
} |
|||
|
|||
void DeleteStoredPrefabNavMeshDataAsset(NavMeshSurface surface) |
|||
{ |
|||
for (var i = m_PrefabNavMeshDataAssets.Count - 1; i >= 0; i--) |
|||
{ |
|||
var storedAssetInfo = m_PrefabNavMeshDataAssets[i]; |
|||
if (storedAssetInfo.surface == surface) |
|||
{ |
|||
var storedNavMeshData = storedAssetInfo.navMeshData; |
|||
if (storedNavMeshData != null && storedNavMeshData != surface.navMeshData) |
|||
{ |
|||
var assetPath = AssetDatabase.GetAssetPath(storedNavMeshData); |
|||
AssetDatabase.DeleteAsset(assetPath); |
|||
} |
|||
|
|||
m_PrefabNavMeshDataAssets.RemoveAt(i); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (m_PrefabNavMeshDataAssets.Count == 0) |
|||
{ |
|||
PrefabStage.prefabSaving -= DeleteStoredNavMeshDataAssetsForOwnedSurfaces; |
|||
PrefabStage.prefabStageClosing -= ForgetUnsavedNavMeshDataChanges; |
|||
} |
|||
} |
|||
|
|||
void ForgetUnsavedNavMeshDataChanges(PrefabStage prefabStage) |
|||
{ |
|||
// Debug.Log("On prefab closing - forget about this object's surfaces and stop caring about prefab saving");
|
|||
|
|||
if (prefabStage == null) |
|||
return; |
|||
|
|||
var allSurfacesInPrefab = prefabStage.prefabContentsRoot.GetComponentsInChildren<NavMeshSurface>(true); |
|||
NavMeshSurface surfaceInPrefab = null; |
|||
var index = 0; |
|||
do |
|||
{ |
|||
if (allSurfacesInPrefab.Length > 0) |
|||
surfaceInPrefab = allSurfacesInPrefab[index]; |
|||
|
|||
for (var i = m_PrefabNavMeshDataAssets.Count - 1; i >= 0; i--) |
|||
{ |
|||
var storedPrefabInfo = m_PrefabNavMeshDataAssets[i]; |
|||
if (storedPrefabInfo.surface == null) |
|||
{ |
|||
// Debug.LogFormat("A surface from the prefab got deleted after it has baked a new NavMesh but it hasn't saved it. Now the unsaved asset gets deleted. ({0})", storedPrefabInfo.navMeshData);
|
|||
|
|||
// surface got deleted, thus delete its initial NavMeshData asset
|
|||
if (storedPrefabInfo.navMeshData != null) |
|||
{ |
|||
var assetPath = AssetDatabase.GetAssetPath(storedPrefabInfo.navMeshData); |
|||
AssetDatabase.DeleteAsset(assetPath); |
|||
} |
|||
|
|||
m_PrefabNavMeshDataAssets.RemoveAt(i); |
|||
} |
|||
else if (surfaceInPrefab != null && storedPrefabInfo.surface == surfaceInPrefab) |
|||
{ |
|||
//Debug.LogFormat("The surface {0} from the prefab was storing the original navmesh data and now will be forgotten", surfaceInPrefab);
|
|||
|
|||
var baseSurface = PrefabUtility.GetCorrespondingObjectFromSource(surfaceInPrefab) as NavMeshSurface; |
|||
if (baseSurface == null || surfaceInPrefab.navMeshData != baseSurface.navMeshData) |
|||
{ |
|||
var assetPath = AssetDatabase.GetAssetPath(surfaceInPrefab.navMeshData); |
|||
AssetDatabase.DeleteAsset(assetPath); |
|||
|
|||
//Debug.LogFormat("The surface {0} from the prefab has baked new NavMeshData but did not save this change so the asset has been now deleted. ({1})",
|
|||
// surfaceInPrefab, assetPath);
|
|||
} |
|||
|
|||
m_PrefabNavMeshDataAssets.RemoveAt(i); |
|||
} |
|||
} |
|||
} while (++index < allSurfacesInPrefab.Length); |
|||
|
|||
if (m_PrefabNavMeshDataAssets.Count == 0) |
|||
{ |
|||
PrefabStage.prefabSaving -= DeleteStoredNavMeshDataAssetsForOwnedSurfaces; |
|||
PrefabStage.prefabStageClosing -= ForgetUnsavedNavMeshDataChanges; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 178d8366aa1616849b91b66285c51454 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 86c9d8e67265f41469be06142c397d17 |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.AI; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
public static class NavMeshComponentsGUIUtility |
|||
{ |
|||
public static void AreaPopup(string labelName, SerializedProperty areaProperty) |
|||
{ |
|||
var areaIndex = -1; |
|||
var areaNames = GameObjectUtility.GetNavMeshAreaNames(); |
|||
for (var i = 0; i < areaNames.Length; i++) |
|||
{ |
|||
var areaValue = GameObjectUtility.GetNavMeshAreaFromName(areaNames[i]); |
|||
if (areaValue == areaProperty.intValue) |
|||
areaIndex = i; |
|||
} |
|||
ArrayUtility.Add(ref areaNames, ""); |
|||
ArrayUtility.Add(ref areaNames, "Open Area Settings..."); |
|||
|
|||
var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); |
|||
EditorGUI.BeginProperty(rect, GUIContent.none, areaProperty); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
areaIndex = EditorGUI.Popup(rect, labelName, areaIndex, areaNames); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
if (areaIndex >= 0 && areaIndex < areaNames.Length - 2) |
|||
areaProperty.intValue = GameObjectUtility.GetNavMeshAreaFromName(areaNames[areaIndex]); |
|||
else if (areaIndex == areaNames.Length - 1) |
|||
NavMeshEditorHelpers.OpenAreaSettings(); |
|||
} |
|||
|
|||
EditorGUI.EndProperty(); |
|||
} |
|||
|
|||
public static void AgentTypePopup(string labelName, SerializedProperty agentTypeID) |
|||
{ |
|||
var index = -1; |
|||
var count = NavMesh.GetSettingsCount(); |
|||
var agentTypeNames = new string[count + 2]; |
|||
for (var i = 0; i < count; i++) |
|||
{ |
|||
var id = NavMesh.GetSettingsByIndex(i).agentTypeID; |
|||
var name = NavMesh.GetSettingsNameFromID(id); |
|||
agentTypeNames[i] = name; |
|||
if (id == agentTypeID.intValue) |
|||
index = i; |
|||
} |
|||
agentTypeNames[count] = ""; |
|||
agentTypeNames[count + 1] = "Open Agent Settings..."; |
|||
|
|||
bool validAgentType = index != -1; |
|||
if (!validAgentType) |
|||
{ |
|||
EditorGUILayout.HelpBox("Agent Type invalid.", MessageType.Warning); |
|||
} |
|||
|
|||
var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); |
|||
EditorGUI.BeginProperty(rect, GUIContent.none, agentTypeID); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
index = EditorGUI.Popup(rect, labelName, index, agentTypeNames); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
if (index >= 0 && index < count) |
|||
{ |
|||
var id = NavMesh.GetSettingsByIndex(index).agentTypeID; |
|||
agentTypeID.intValue = id; |
|||
} |
|||
else if (index == count + 1) |
|||
{ |
|||
NavMeshEditorHelpers.OpenAgentSettings(-1); |
|||
} |
|||
} |
|||
|
|||
EditorGUI.EndProperty(); |
|||
} |
|||
|
|||
// Agent mask is a set (internally array/list) of agentTypeIDs.
|
|||
// It is used to describe which agents modifiers apply to.
|
|||
// There is a special case of "None" which is an empty array.
|
|||
// There is a special case of "All" which is an array of length 1, and value of -1.
|
|||
public static void AgentMaskPopup(string labelName, SerializedProperty agentMask) |
|||
{ |
|||
// Contents of the dropdown box.
|
|||
string popupContent = ""; |
|||
|
|||
if (agentMask.hasMultipleDifferentValues) |
|||
popupContent = "\u2014"; |
|||
else |
|||
popupContent = GetAgentMaskLabelName(agentMask); |
|||
|
|||
var content = new GUIContent(popupContent); |
|||
var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); |
|||
|
|||
EditorGUI.BeginProperty(popupRect, GUIContent.none, agentMask); |
|||
popupRect = EditorGUI.PrefixLabel(popupRect, 0, new GUIContent(labelName)); |
|||
bool pressed = GUI.Button(popupRect, content, EditorStyles.popup); |
|||
|
|||
if (pressed) |
|||
{ |
|||
var show = !agentMask.hasMultipleDifferentValues; |
|||
var showNone = show && agentMask.arraySize == 0; |
|||
var showAll = show && IsAll(agentMask); |
|||
|
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(new GUIContent("None"), showNone, SetAgentMaskNone, agentMask); |
|||
menu.AddItem(new GUIContent("All"), showAll, SetAgentMaskAll, agentMask); |
|||
menu.AddSeparator(""); |
|||
|
|||
var count = NavMesh.GetSettingsCount(); |
|||
for (var i = 0; i < count; i++) |
|||
{ |
|||
var id = NavMesh.GetSettingsByIndex(i).agentTypeID; |
|||
var sname = NavMesh.GetSettingsNameFromID(id); |
|||
|
|||
var showSelected = show && AgentMaskHasSelectedAgentTypeID(agentMask, id); |
|||
var userData = new object[] { agentMask, id, !showSelected }; |
|||
menu.AddItem(new GUIContent(sname), showSelected, ToggleAgentMaskItem, userData); |
|||
} |
|||
|
|||
menu.DropDown(popupRect); |
|||
} |
|||
|
|||
EditorGUI.EndProperty(); |
|||
} |
|||
|
|||
public static GameObject CreateAndSelectGameObject(string suggestedName, GameObject parent) |
|||
{ |
|||
var parentTransform = parent != null ? parent.transform : null; |
|||
var uniqueName = GameObjectUtility.GetUniqueNameForSibling(parentTransform, suggestedName); |
|||
var child = new GameObject(uniqueName); |
|||
|
|||
Undo.RegisterCreatedObjectUndo(child, "Create " + uniqueName); |
|||
if (parentTransform != null) |
|||
Undo.SetTransformParent(child.transform, parentTransform, "Parent " + uniqueName); |
|||
|
|||
Selection.activeGameObject = child; |
|||
|
|||
return child; |
|||
} |
|||
|
|||
static bool IsAll(SerializedProperty agentMask) |
|||
{ |
|||
return agentMask.arraySize == 1 && agentMask.GetArrayElementAtIndex(0).intValue == -1; |
|||
} |
|||
|
|||
static void ToggleAgentMaskItem(object userData) |
|||
{ |
|||
var args = (object[])userData; |
|||
var agentMask = (SerializedProperty)args[0]; |
|||
var agentTypeID = (int)args[1]; |
|||
var value = (bool)args[2]; |
|||
|
|||
ToggleAgentMaskItem(agentMask, agentTypeID, value); |
|||
} |
|||
|
|||
static void ToggleAgentMaskItem(SerializedProperty agentMask, int agentTypeID, bool value) |
|||
{ |
|||
if (agentMask.hasMultipleDifferentValues) |
|||
{ |
|||
agentMask.ClearArray(); |
|||
agentMask.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
// Find which index this agent type is in the agentMask array.
|
|||
int idx = -1; |
|||
for (var j = 0; j < agentMask.arraySize; j++) |
|||
{ |
|||
var elem = agentMask.GetArrayElementAtIndex(j); |
|||
if (elem.intValue == agentTypeID) |
|||
idx = j; |
|||
} |
|||
|
|||
// Handle "All" special case.
|
|||
if (IsAll(agentMask)) |
|||
{ |
|||
agentMask.DeleteArrayElementAtIndex(0); |
|||
} |
|||
|
|||
// Toggle value.
|
|||
if (value) |
|||
{ |
|||
if (idx == -1) |
|||
{ |
|||
agentMask.InsertArrayElementAtIndex(agentMask.arraySize); |
|||
agentMask.GetArrayElementAtIndex(agentMask.arraySize - 1).intValue = agentTypeID; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (idx != -1) |
|||
{ |
|||
agentMask.DeleteArrayElementAtIndex(idx); |
|||
} |
|||
} |
|||
|
|||
agentMask.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
static void SetAgentMaskNone(object data) |
|||
{ |
|||
var agentMask = (SerializedProperty)data; |
|||
agentMask.ClearArray(); |
|||
agentMask.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
static void SetAgentMaskAll(object data) |
|||
{ |
|||
var agentMask = (SerializedProperty)data; |
|||
agentMask.ClearArray(); |
|||
agentMask.InsertArrayElementAtIndex(0); |
|||
agentMask.GetArrayElementAtIndex(0).intValue = -1; |
|||
agentMask.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
static string GetAgentMaskLabelName(SerializedProperty agentMask) |
|||
{ |
|||
if (agentMask.arraySize == 0) |
|||
return "None"; |
|||
|
|||
if (IsAll(agentMask)) |
|||
return "All"; |
|||
|
|||
if (agentMask.arraySize <= 3) |
|||
{ |
|||
var labelName = ""; |
|||
for (var j = 0; j < agentMask.arraySize; j++) |
|||
{ |
|||
var elem = agentMask.GetArrayElementAtIndex(j); |
|||
var settingsName = NavMesh.GetSettingsNameFromID(elem.intValue); |
|||
if (string.IsNullOrEmpty(settingsName)) |
|||
continue; |
|||
|
|||
if (labelName.Length > 0) |
|||
labelName += ", "; |
|||
labelName += settingsName; |
|||
} |
|||
return labelName; |
|||
} |
|||
|
|||
return "Mixed..."; |
|||
} |
|||
|
|||
static bool AgentMaskHasSelectedAgentTypeID(SerializedProperty agentMask, int agentTypeID) |
|||
{ |
|||
for (var j = 0; j < agentMask.arraySize; j++) |
|||
{ |
|||
var elem = agentMask.GetArrayElementAtIndex(j); |
|||
if (elem.intValue == agentTypeID) |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 77fba670b979046f18d52d751e0d4659 |
|||
timeCreated: 1480524815 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.AI; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
[CanEditMultipleObjects] |
|||
[CustomEditor(typeof(NavMeshLink))] |
|||
class NavMeshLinkEditor : Editor |
|||
{ |
|||
SerializedProperty m_AgentTypeID; |
|||
SerializedProperty m_Area; |
|||
SerializedProperty m_CostModifier; |
|||
SerializedProperty m_AutoUpdatePosition; |
|||
SerializedProperty m_Bidirectional; |
|||
SerializedProperty m_EndPoint; |
|||
SerializedProperty m_StartPoint; |
|||
SerializedProperty m_Width; |
|||
|
|||
static int s_SelectedID; |
|||
static int s_SelectedPoint = -1; |
|||
|
|||
static Color s_HandleColor = new Color(255f, 167f, 39f, 210f) / 255; |
|||
static Color s_HandleColorDisabled = new Color(255f * 0.75f, 167f * 0.75f, 39f * 0.75f, 100f) / 255; |
|||
|
|||
void OnEnable() |
|||
{ |
|||
m_AgentTypeID = serializedObject.FindProperty("m_AgentTypeID"); |
|||
m_Area = serializedObject.FindProperty("m_Area"); |
|||
m_CostModifier = serializedObject.FindProperty("m_CostModifier"); |
|||
m_AutoUpdatePosition = serializedObject.FindProperty("m_AutoUpdatePosition"); |
|||
m_Bidirectional = serializedObject.FindProperty("m_Bidirectional"); |
|||
m_EndPoint = serializedObject.FindProperty("m_EndPoint"); |
|||
m_StartPoint = serializedObject.FindProperty("m_StartPoint"); |
|||
m_Width = serializedObject.FindProperty("m_Width"); |
|||
|
|||
s_SelectedID = 0; |
|||
s_SelectedPoint = -1; |
|||
|
|||
NavMeshVisualizationSettings.showNavigation++; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
NavMeshVisualizationSettings.showNavigation--; |
|||
} |
|||
|
|||
static Matrix4x4 UnscaledLocalToWorldMatrix(Transform t) |
|||
{ |
|||
return Matrix4x4.TRS(t.position, t.rotation, Vector3.one); |
|||
} |
|||
|
|||
void AlignTransformToEndPoints(NavMeshLink navLink) |
|||
{ |
|||
var mat = UnscaledLocalToWorldMatrix(navLink.transform); |
|||
|
|||
var worldStartPt = mat.MultiplyPoint(navLink.startPoint); |
|||
var worldEndPt = mat.MultiplyPoint(navLink.endPoint); |
|||
|
|||
var forward = worldEndPt - worldStartPt; |
|||
var up = navLink.transform.up; |
|||
|
|||
// Flatten
|
|||
forward -= Vector3.Dot(up, forward) * up; |
|||
|
|||
var transform = navLink.transform; |
|||
transform.rotation = Quaternion.LookRotation(forward, up); |
|||
transform.position = (worldEndPt + worldStartPt) * 0.5f; |
|||
transform.localScale = Vector3.one; |
|||
|
|||
navLink.startPoint = transform.InverseTransformPoint(worldStartPt); |
|||
navLink.endPoint = transform.InverseTransformPoint(worldEndPt); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
NavMeshComponentsGUIUtility.AgentTypePopup("Agent Type", m_AgentTypeID); |
|||
EditorGUILayout.Space(); |
|||
|
|||
EditorGUILayout.PropertyField(m_StartPoint); |
|||
EditorGUILayout.PropertyField(m_EndPoint); |
|||
|
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Space(EditorGUIUtility.labelWidth); |
|||
if (GUILayout.Button("Swap")) |
|||
{ |
|||
foreach (NavMeshLink navLink in targets) |
|||
{ |
|||
var tmp = navLink.startPoint; |
|||
navLink.startPoint = navLink.endPoint; |
|||
navLink.endPoint = tmp; |
|||
} |
|||
SceneView.RepaintAll(); |
|||
} |
|||
if (GUILayout.Button("Align Transform")) |
|||
{ |
|||
foreach (NavMeshLink navLink in targets) |
|||
{ |
|||
Undo.RecordObject(navLink.transform, "Align Transform to End Points"); |
|||
Undo.RecordObject(navLink, "Align Transform to End Points"); |
|||
AlignTransformToEndPoints(navLink); |
|||
} |
|||
SceneView.RepaintAll(); |
|||
} |
|||
GUILayout.EndHorizontal(); |
|||
EditorGUILayout.Space(); |
|||
|
|||
EditorGUILayout.PropertyField(m_Width); |
|||
EditorGUILayout.PropertyField(m_CostModifier); |
|||
EditorGUILayout.PropertyField(m_AutoUpdatePosition); |
|||
EditorGUILayout.PropertyField(m_Bidirectional); |
|||
|
|||
NavMeshComponentsGUIUtility.AreaPopup("Area Type", m_Area); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
|
|||
EditorGUILayout.Space(); |
|||
} |
|||
|
|||
static Vector3 CalcLinkRight(NavMeshLink navLink) |
|||
{ |
|||
var dir = navLink.endPoint - navLink.startPoint; |
|||
return (new Vector3(-dir.z, 0.0f, dir.x)).normalized; |
|||
} |
|||
|
|||
static void DrawLink(NavMeshLink navLink) |
|||
{ |
|||
var right = CalcLinkRight(navLink); |
|||
var rad = navLink.width * 0.5f; |
|||
|
|||
Gizmos.DrawLine(navLink.startPoint - right * rad, navLink.startPoint + right * rad); |
|||
Gizmos.DrawLine(navLink.endPoint - right * rad, navLink.endPoint + right * rad); |
|||
Gizmos.DrawLine(navLink.startPoint - right * rad, navLink.endPoint - right * rad); |
|||
Gizmos.DrawLine(navLink.startPoint + right * rad, navLink.endPoint + right * rad); |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)] |
|||
static void RenderBoxGizmo(NavMeshLink navLink, GizmoType gizmoType) |
|||
{ |
|||
if (!EditorApplication.isPlaying) |
|||
navLink.UpdateLink(); |
|||
|
|||
var color = s_HandleColor; |
|||
if (!navLink.enabled) |
|||
color = s_HandleColorDisabled; |
|||
|
|||
var oldColor = Gizmos.color; |
|||
var oldMatrix = Gizmos.matrix; |
|||
|
|||
Gizmos.matrix = UnscaledLocalToWorldMatrix(navLink.transform); |
|||
|
|||
Gizmos.color = color; |
|||
DrawLink(navLink); |
|||
|
|||
Gizmos.matrix = oldMatrix; |
|||
Gizmos.color = oldColor; |
|||
|
|||
Gizmos.DrawIcon(navLink.transform.position, "NavMeshLink Icon", true); |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)] |
|||
static void RenderBoxGizmoNotSelected(NavMeshLink navLink, GizmoType gizmoType) |
|||
{ |
|||
if (NavMeshVisualizationSettings.showNavigation > 0) |
|||
{ |
|||
var color = s_HandleColor; |
|||
if (!navLink.enabled) |
|||
color = s_HandleColorDisabled; |
|||
|
|||
var oldColor = Gizmos.color; |
|||
var oldMatrix = Gizmos.matrix; |
|||
|
|||
Gizmos.matrix = UnscaledLocalToWorldMatrix(navLink.transform); |
|||
|
|||
Gizmos.color = color; |
|||
DrawLink(navLink); |
|||
|
|||
Gizmos.matrix = oldMatrix; |
|||
Gizmos.color = oldColor; |
|||
} |
|||
|
|||
Gizmos.DrawIcon(navLink.transform.position, "NavMeshLink Icon", true); |
|||
} |
|||
|
|||
public void OnSceneGUI() |
|||
{ |
|||
var navLink = (NavMeshLink)target; |
|||
if (!navLink.enabled) |
|||
return; |
|||
|
|||
var mat = UnscaledLocalToWorldMatrix(navLink.transform); |
|||
|
|||
var startPt = mat.MultiplyPoint(navLink.startPoint); |
|||
var endPt = mat.MultiplyPoint(navLink.endPoint); |
|||
var midPt = Vector3.Lerp(startPt, endPt, 0.35f); |
|||
var startSize = HandleUtility.GetHandleSize(startPt); |
|||
var endSize = HandleUtility.GetHandleSize(endPt); |
|||
var midSize = HandleUtility.GetHandleSize(midPt); |
|||
|
|||
var zup = Quaternion.FromToRotation(Vector3.forward, Vector3.up); |
|||
var right = mat.MultiplyVector(CalcLinkRight(navLink)); |
|||
|
|||
var oldColor = Handles.color; |
|||
Handles.color = s_HandleColor; |
|||
|
|||
Vector3 pos; |
|||
|
|||
if (navLink.GetInstanceID() == s_SelectedID && s_SelectedPoint == 0) |
|||
{ |
|||
EditorGUI.BeginChangeCheck(); |
|||
Handles.CubeHandleCap(0, startPt, zup, 0.1f * startSize, Event.current.type); |
|||
pos = Handles.PositionHandle(startPt, navLink.transform.rotation); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(navLink, "Move link point"); |
|||
navLink.startPoint = mat.inverse.MultiplyPoint(pos); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (Handles.Button(startPt, zup, 0.1f * startSize, 0.1f * startSize, Handles.CubeHandleCap)) |
|||
{ |
|||
s_SelectedPoint = 0; |
|||
s_SelectedID = navLink.GetInstanceID(); |
|||
} |
|||
} |
|||
|
|||
if (navLink.GetInstanceID() == s_SelectedID && s_SelectedPoint == 1) |
|||
{ |
|||
EditorGUI.BeginChangeCheck(); |
|||
Handles.CubeHandleCap(0, endPt, zup, 0.1f * startSize, Event.current.type); |
|||
pos = Handles.PositionHandle(endPt, navLink.transform.rotation); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(navLink, "Move link point"); |
|||
navLink.endPoint = mat.inverse.MultiplyPoint(pos); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (Handles.Button(endPt, zup, 0.1f * endSize, 0.1f * endSize, Handles.CubeHandleCap)) |
|||
{ |
|||
s_SelectedPoint = 1; |
|||
s_SelectedID = navLink.GetInstanceID(); |
|||
} |
|||
} |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
pos = Handles.Slider(midPt + right * navLink.width * 0.5f, right, midSize * 0.03f, Handles.DotHandleCap, 0); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(navLink, "Adjust link width"); |
|||
navLink.width = Mathf.Max(0.0f, 2.0f * Vector3.Dot(right, (pos - midPt))); |
|||
} |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
pos = Handles.Slider(midPt - right * navLink.width * 0.5f, -right, midSize * 0.03f, Handles.DotHandleCap, 0); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(navLink, "Adjust link width"); |
|||
navLink.width = Mathf.Max(0.0f, 2.0f * Vector3.Dot(-right, (pos - midPt))); |
|||
} |
|||
|
|||
Handles.color = oldColor; |
|||
} |
|||
|
|||
[MenuItem("GameObject/AI/NavMesh Link", false, 2002)] |
|||
static public void CreateNavMeshLink(MenuCommand menuCommand) |
|||
{ |
|||
var parent = menuCommand.context as GameObject; |
|||
GameObject go = NavMeshComponentsGUIUtility.CreateAndSelectGameObject("NavMesh Link", parent); |
|||
go.AddComponent<NavMeshLink>(); |
|||
var view = SceneView.lastActiveSceneView; |
|||
if (view != null) |
|||
view.MoveToView(go.transform); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ece1e865d1ad84587872fe8580ab5a20 |
|||
timeCreated: 1477036743 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine.AI; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
[CanEditMultipleObjects] |
|||
[CustomEditor(typeof(NavMeshModifier))] |
|||
class NavMeshModifierEditor : Editor |
|||
{ |
|||
SerializedProperty m_AffectedAgents; |
|||
SerializedProperty m_Area; |
|||
SerializedProperty m_IgnoreFromBuild; |
|||
SerializedProperty m_OverrideArea; |
|||
|
|||
void OnEnable() |
|||
{ |
|||
m_AffectedAgents = serializedObject.FindProperty("m_AffectedAgents"); |
|||
m_Area = serializedObject.FindProperty("m_Area"); |
|||
m_IgnoreFromBuild = serializedObject.FindProperty("m_IgnoreFromBuild"); |
|||
m_OverrideArea = serializedObject.FindProperty("m_OverrideArea"); |
|||
|
|||
NavMeshVisualizationSettings.showNavigation++; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
NavMeshVisualizationSettings.showNavigation--; |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
EditorGUILayout.PropertyField(m_IgnoreFromBuild); |
|||
|
|||
EditorGUILayout.PropertyField(m_OverrideArea); |
|||
if (m_OverrideArea.boolValue) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
NavMeshComponentsGUIUtility.AreaPopup("Area Type", m_Area); |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
|
|||
NavMeshComponentsGUIUtility.AgentMaskPopup("Affected Agents", m_AffectedAgents); |
|||
EditorGUILayout.Space(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6fa04b4743e3947eba4d7b9e5832ea69 |
|||
timeCreated: 1477036742 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.IMGUI.Controls; |
|||
using UnityEditorInternal; |
|||
using UnityEngine.AI; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
[CanEditMultipleObjects] |
|||
[CustomEditor(typeof(NavMeshModifierVolume))] |
|||
class NavMeshModifierVolumeEditor : Editor |
|||
{ |
|||
SerializedProperty m_AffectedAgents; |
|||
SerializedProperty m_Area; |
|||
SerializedProperty m_Center; |
|||
SerializedProperty m_Size; |
|||
|
|||
static Color s_HandleColor = new Color(187f, 138f, 240f, 210f) / 255; |
|||
static Color s_HandleColorDisabled = new Color(187f * 0.75f, 138f * 0.75f, 240f * 0.75f, 100f) / 255; |
|||
|
|||
BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); |
|||
|
|||
bool editingCollider |
|||
{ |
|||
get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
m_AffectedAgents = serializedObject.FindProperty("m_AffectedAgents"); |
|||
m_Area = serializedObject.FindProperty("m_Area"); |
|||
m_Center = serializedObject.FindProperty("m_Center"); |
|||
m_Size = serializedObject.FindProperty("m_Size"); |
|||
|
|||
NavMeshVisualizationSettings.showNavigation++; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
NavMeshVisualizationSettings.showNavigation--; |
|||
} |
|||
|
|||
Bounds GetBounds() |
|||
{ |
|||
var navModifier = (NavMeshModifierVolume)target; |
|||
return new Bounds(navModifier.transform.position, navModifier.size); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
EditMode.DoEditModeInspectorModeButton(EditMode.SceneViewEditMode.Collider, "Edit Volume", |
|||
EditorGUIUtility.IconContent("EditCollider"), GetBounds, this); |
|||
|
|||
EditorGUILayout.PropertyField(m_Size); |
|||
EditorGUILayout.PropertyField(m_Center); |
|||
|
|||
NavMeshComponentsGUIUtility.AreaPopup("Area Type", m_Area); |
|||
NavMeshComponentsGUIUtility.AgentMaskPopup("Affected Agents", m_AffectedAgents); |
|||
EditorGUILayout.Space(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.Selected | GizmoType.Active)] |
|||
static void RenderBoxGizmo(NavMeshModifierVolume navModifier, GizmoType gizmoType) |
|||
{ |
|||
var color = navModifier.enabled ? s_HandleColor : s_HandleColorDisabled; |
|||
var colorTrans = new Color(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, color.a * 0.15f); |
|||
|
|||
var oldColor = Gizmos.color; |
|||
var oldMatrix = Gizmos.matrix; |
|||
|
|||
Gizmos.matrix = navModifier.transform.localToWorldMatrix; |
|||
|
|||
Gizmos.color = colorTrans; |
|||
Gizmos.DrawCube(navModifier.center, navModifier.size); |
|||
|
|||
Gizmos.color = color; |
|||
Gizmos.DrawWireCube(navModifier.center, navModifier.size); |
|||
|
|||
Gizmos.matrix = oldMatrix; |
|||
Gizmos.color = oldColor; |
|||
|
|||
Gizmos.DrawIcon(navModifier.transform.position, "NavMeshModifierVolume Icon", true); |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)] |
|||
static void RenderBoxGizmoNotSelected(NavMeshModifierVolume navModifier, GizmoType gizmoType) |
|||
{ |
|||
if (NavMeshVisualizationSettings.showNavigation > 0) |
|||
{ |
|||
var color = navModifier.enabled ? s_HandleColor : s_HandleColorDisabled; |
|||
var oldColor = Gizmos.color; |
|||
var oldMatrix = Gizmos.matrix; |
|||
|
|||
Gizmos.matrix = navModifier.transform.localToWorldMatrix; |
|||
|
|||
Gizmos.color = color; |
|||
Gizmos.DrawWireCube(navModifier.center, navModifier.size); |
|||
|
|||
Gizmos.matrix = oldMatrix; |
|||
Gizmos.color = oldColor; |
|||
} |
|||
|
|||
Gizmos.DrawIcon(navModifier.transform.position, "NavMeshModifierVolume Icon", true); |
|||
} |
|||
|
|||
void OnSceneGUI() |
|||
{ |
|||
if (!editingCollider) |
|||
return; |
|||
|
|||
var vol = (NavMeshModifierVolume)target; |
|||
var color = vol.enabled ? s_HandleColor : s_HandleColorDisabled; |
|||
using (new Handles.DrawingScope(color, vol.transform.localToWorldMatrix)) |
|||
{ |
|||
m_BoundsHandle.center = vol.center; |
|||
m_BoundsHandle.size = vol.size; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_BoundsHandle.DrawHandle(); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(vol, "Modified NavMesh Modifier Volume"); |
|||
Vector3 center = m_BoundsHandle.center; |
|||
Vector3 size = m_BoundsHandle.size; |
|||
vol.center = center; |
|||
vol.size = size; |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[MenuItem("GameObject/AI/NavMesh Modifier Volume", false, 2001)] |
|||
static public void CreateNavMeshModifierVolume(MenuCommand menuCommand) |
|||
{ |
|||
var parent = menuCommand.context as GameObject; |
|||
var go = NavMeshComponentsGUIUtility.CreateAndSelectGameObject("NavMesh Modifier Volume", parent); |
|||
go.AddComponent<NavMeshModifierVolume>(); |
|||
var view = SceneView.lastActiveSceneView; |
|||
if (view != null) |
|||
view.MoveToView(go.transform); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c0f3bef2a67ae4e139538afec3e59b03 |
|||
timeCreated: 1477036743 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#define NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEditor.Experimental.SceneManagement; |
|||
using UnityEditor.IMGUI.Controls; |
|||
using UnityEditor.SceneManagement; |
|||
using UnityEditorInternal; |
|||
using UnityEngine.AI; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.AI |
|||
{ |
|||
[CanEditMultipleObjects] |
|||
[CustomEditor(typeof(NavMeshSurface))] |
|||
class NavMeshSurfaceEditor : Editor |
|||
{ |
|||
SerializedProperty m_AgentTypeID; |
|||
SerializedProperty m_BuildHeightMesh; |
|||
SerializedProperty m_Center; |
|||
SerializedProperty m_CollectObjects; |
|||
SerializedProperty m_DefaultArea; |
|||
SerializedProperty m_LayerMask; |
|||
SerializedProperty m_OverrideTileSize; |
|||
SerializedProperty m_OverrideVoxelSize; |
|||
SerializedProperty m_Size; |
|||
SerializedProperty m_TileSize; |
|||
SerializedProperty m_UseGeometry; |
|||
SerializedProperty m_VoxelSize; |
|||
|
|||
#if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
|
|||
SerializedProperty m_NavMeshData; |
|||
#endif
|
|||
class Styles |
|||
{ |
|||
public readonly GUIContent m_LayerMask = new GUIContent("Include Layers"); |
|||
|
|||
public readonly GUIContent m_ShowInputGeom = new GUIContent("Show Input Geom"); |
|||
public readonly GUIContent m_ShowVoxels = new GUIContent("Show Voxels"); |
|||
public readonly GUIContent m_ShowRegions = new GUIContent("Show Regions"); |
|||
public readonly GUIContent m_ShowRawContours = new GUIContent("Show Raw Contours"); |
|||
public readonly GUIContent m_ShowContours = new GUIContent("Show Contours"); |
|||
public readonly GUIContent m_ShowPolyMesh = new GUIContent("Show Poly Mesh"); |
|||
public readonly GUIContent m_ShowPolyMeshDetail = new GUIContent("Show Poly Mesh Detail"); |
|||
} |
|||
|
|||
static Styles s_Styles; |
|||
|
|||
static bool s_ShowDebugOptions; |
|||
|
|||
static Color s_HandleColor = new Color(127f, 214f, 244f, 100f) / 255; |
|||
static Color s_HandleColorSelected = new Color(127f, 214f, 244f, 210f) / 255; |
|||
static Color s_HandleColorDisabled = new Color(127f * 0.75f, 214f * 0.75f, 244f * 0.75f, 100f) / 255; |
|||
|
|||
BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); |
|||
|
|||
bool editingCollider |
|||
{ |
|||
get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
m_AgentTypeID = serializedObject.FindProperty("m_AgentTypeID"); |
|||
m_BuildHeightMesh = serializedObject.FindProperty("m_BuildHeightMesh"); |
|||
m_Center = serializedObject.FindProperty("m_Center"); |
|||
m_CollectObjects = serializedObject.FindProperty("m_CollectObjects"); |
|||
m_DefaultArea = serializedObject.FindProperty("m_DefaultArea"); |
|||
m_LayerMask = serializedObject.FindProperty("m_LayerMask"); |
|||
m_OverrideTileSize = serializedObject.FindProperty("m_OverrideTileSize"); |
|||
m_OverrideVoxelSize = serializedObject.FindProperty("m_OverrideVoxelSize"); |
|||
m_Size = serializedObject.FindProperty("m_Size"); |
|||
m_TileSize = serializedObject.FindProperty("m_TileSize"); |
|||
m_UseGeometry = serializedObject.FindProperty("m_UseGeometry"); |
|||
m_VoxelSize = serializedObject.FindProperty("m_VoxelSize"); |
|||
|
|||
#if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
|
|||
m_NavMeshData = serializedObject.FindProperty("m_NavMeshData"); |
|||
#endif
|
|||
NavMeshVisualizationSettings.showNavigation++; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
NavMeshVisualizationSettings.showNavigation--; |
|||
} |
|||
|
|||
Bounds GetBounds() |
|||
{ |
|||
var navSurface = (NavMeshSurface)target; |
|||
return new Bounds(navSurface.transform.position, navSurface.size); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
if (s_Styles == null) |
|||
s_Styles = new Styles(); |
|||
|
|||
serializedObject.Update(); |
|||
|
|||
var bs = NavMesh.GetSettingsByID(m_AgentTypeID.intValue); |
|||
|
|||
if (bs.agentTypeID != -1) |
|||
{ |
|||
// Draw image
|
|||
const float diagramHeight = 80.0f; |
|||
Rect agentDiagramRect = EditorGUILayout.GetControlRect(false, diagramHeight); |
|||
NavMeshEditorHelpers.DrawAgentDiagram(agentDiagramRect, bs.agentRadius, bs.agentHeight, bs.agentClimb, bs.agentSlope); |
|||
} |
|||
NavMeshComponentsGUIUtility.AgentTypePopup("Agent Type", m_AgentTypeID); |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
EditorGUILayout.PropertyField(m_CollectObjects); |
|||
if ((CollectObjects)m_CollectObjects.enumValueIndex == CollectObjects.Volume) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
|
|||
EditMode.DoEditModeInspectorModeButton(EditMode.SceneViewEditMode.Collider, "Edit Volume", |
|||
EditorGUIUtility.IconContent("EditCollider"), GetBounds, this); |
|||
EditorGUILayout.PropertyField(m_Size); |
|||
EditorGUILayout.PropertyField(m_Center); |
|||
|
|||
EditorGUI.indentLevel--; |
|||
} |
|||
else |
|||
{ |
|||
if (editingCollider) |
|||
EditMode.QuitEditMode(); |
|||
} |
|||
|
|||
EditorGUILayout.PropertyField(m_LayerMask, s_Styles.m_LayerMask); |
|||
EditorGUILayout.PropertyField(m_UseGeometry); |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
m_OverrideVoxelSize.isExpanded = EditorGUILayout.Foldout(m_OverrideVoxelSize.isExpanded, "Advanced"); |
|||
if (m_OverrideVoxelSize.isExpanded) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
|
|||
NavMeshComponentsGUIUtility.AreaPopup("Default Area", m_DefaultArea); |
|||
|
|||
// Override voxel size.
|
|||
EditorGUILayout.PropertyField(m_OverrideVoxelSize); |
|||
|
|||
using (new EditorGUI.DisabledScope(!m_OverrideVoxelSize.boolValue || m_OverrideVoxelSize.hasMultipleDifferentValues)) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
|
|||
EditorGUILayout.PropertyField(m_VoxelSize); |
|||
|
|||
if (!m_OverrideVoxelSize.hasMultipleDifferentValues) |
|||
{ |
|||
if (!m_AgentTypeID.hasMultipleDifferentValues) |
|||
{ |
|||
float voxelsPerRadius = m_VoxelSize.floatValue > 0.0f ? (bs.agentRadius / m_VoxelSize.floatValue) : 0.0f; |
|||
EditorGUILayout.LabelField(" ", voxelsPerRadius.ToString("0.00") + " voxels per agent radius", EditorStyles.miniLabel); |
|||
} |
|||
if (m_OverrideVoxelSize.boolValue) |
|||
EditorGUILayout.HelpBox("Voxel size controls how accurately the navigation mesh is generated from the level geometry. A good voxel size is 2-4 voxels per agent radius. Making voxel size smaller will increase build time.", MessageType.None); |
|||
} |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
|
|||
// Override tile size
|
|||
EditorGUILayout.PropertyField(m_OverrideTileSize); |
|||
|
|||
using (new EditorGUI.DisabledScope(!m_OverrideTileSize.boolValue || m_OverrideTileSize.hasMultipleDifferentValues)) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
|
|||
EditorGUILayout.PropertyField(m_TileSize); |
|||
|
|||
if (!m_TileSize.hasMultipleDifferentValues && !m_VoxelSize.hasMultipleDifferentValues) |
|||
{ |
|||
float tileWorldSize = m_TileSize.intValue * m_VoxelSize.floatValue; |
|||
EditorGUILayout.LabelField(" ", tileWorldSize.ToString("0.00") + " world units", EditorStyles.miniLabel); |
|||
} |
|||
|
|||
if (!m_OverrideTileSize.hasMultipleDifferentValues) |
|||
{ |
|||
if (m_OverrideTileSize.boolValue) |
|||
EditorGUILayout.HelpBox("Tile size controls the how local the changes to the world are (rebuild or carve). Small tile size allows more local changes, while potentially generating more data overall.", MessageType.None); |
|||
} |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
|
|||
|
|||
// Height mesh
|
|||
using (new EditorGUI.DisabledScope(true)) |
|||
{ |
|||
EditorGUILayout.PropertyField(m_BuildHeightMesh); |
|||
} |
|||
|
|||
EditorGUILayout.Space(); |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
|
|||
var hadError = false; |
|||
var multipleTargets = targets.Length > 1; |
|||
foreach (NavMeshSurface navSurface in targets) |
|||
{ |
|||
var settings = navSurface.GetBuildSettings(); |
|||
// Calculating bounds is potentially expensive when unbounded - so here we just use the center/size.
|
|||
// It means the validation is not checking vertical voxel limit correctly when the surface is set to something else than "in volume".
|
|||
var bounds = new Bounds(Vector3.zero, Vector3.zero); |
|||
if (navSurface.collectObjects == CollectObjects.Volume) |
|||
{ |
|||
bounds = new Bounds(navSurface.center, navSurface.size); |
|||
} |
|||
|
|||
var errors = settings.ValidationReport(bounds); |
|||
if (errors.Length > 0) |
|||
{ |
|||
if (multipleTargets) |
|||
EditorGUILayout.LabelField(navSurface.name); |
|||
foreach (var err in errors) |
|||
{ |
|||
EditorGUILayout.HelpBox(err, MessageType.Warning); |
|||
} |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Space(EditorGUIUtility.labelWidth); |
|||
if (GUILayout.Button("Open Agent Settings...", EditorStyles.miniButton)) |
|||
NavMeshEditorHelpers.OpenAgentSettings(navSurface.agentTypeID); |
|||
GUILayout.EndHorizontal(); |
|||
hadError = true; |
|||
} |
|||
} |
|||
|
|||
if (hadError) |
|||
EditorGUILayout.Space(); |
|||
|
|||
#if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
|
|||
var nmdRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); |
|||
|
|||
EditorGUI.BeginProperty(nmdRect, GUIContent.none, m_NavMeshData); |
|||
var rectLabel = EditorGUI.PrefixLabel(nmdRect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(m_NavMeshData.displayName)); |
|||
EditorGUI.EndProperty(); |
|||
|
|||
using (new EditorGUI.DisabledScope(true)) |
|||
{ |
|||
EditorGUI.BeginProperty(nmdRect, GUIContent.none, m_NavMeshData); |
|||
EditorGUI.ObjectField(rectLabel, m_NavMeshData, GUIContent.none); |
|||
EditorGUI.EndProperty(); |
|||
} |
|||
#endif
|
|||
using (new EditorGUI.DisabledScope(Application.isPlaying || m_AgentTypeID.intValue == -1)) |
|||
{ |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Space(EditorGUIUtility.labelWidth); |
|||
if (GUILayout.Button("Clear")) |
|||
{ |
|||
NavMeshAssetManager.instance.ClearSurfaces(targets); |
|||
SceneView.RepaintAll(); |
|||
} |
|||
|
|||
if (GUILayout.Button("Bake")) |
|||
{ |
|||
NavMeshAssetManager.instance.StartBakingSurfaces(targets); |
|||
} |
|||
|
|||
GUILayout.EndHorizontal(); |
|||
} |
|||
|
|||
// Show progress for the selected targets
|
|||
var bakeOperations = NavMeshAssetManager.instance.GetBakeOperations(); |
|||
for (int i = bakeOperations.Count - 1; i >= 0; --i) |
|||
{ |
|||
if (!targets.Contains(bakeOperations[i].surface)) |
|||
continue; |
|||
|
|||
var oper = bakeOperations[i].bakeOperation; |
|||
if (oper == null) |
|||
continue; |
|||
|
|||
var p = oper.progress; |
|||
if (oper.isDone) |
|||
{ |
|||
SceneView.RepaintAll(); |
|||
continue; |
|||
} |
|||
|
|||
GUILayout.BeginHorizontal(); |
|||
|
|||
if (GUILayout.Button("Cancel", EditorStyles.miniButton)) |
|||
{ |
|||
var bakeData = bakeOperations[i].bakeData; |
|||
UnityEngine.AI.NavMeshBuilder.Cancel(bakeData); |
|||
bakeOperations.RemoveAt(i); |
|||
} |
|||
|
|||
EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), p, "Baking: " + (int)(100 * p) + "%"); |
|||
if (p <= 1) |
|||
Repaint(); |
|||
|
|||
GUILayout.EndHorizontal(); |
|||
} |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)] |
|||
static void RenderBoxGizmoSelected(NavMeshSurface navSurface, GizmoType gizmoType) |
|||
{ |
|||
RenderBoxGizmo(navSurface, gizmoType, true); |
|||
} |
|||
|
|||
[DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)] |
|||
static void RenderBoxGizmoNotSelected(NavMeshSurface navSurface, GizmoType gizmoType) |
|||
{ |
|||
if (NavMeshVisualizationSettings.showNavigation > 0) |
|||
RenderBoxGizmo(navSurface, gizmoType, false); |
|||
else |
|||
Gizmos.DrawIcon(navSurface.transform.position, "NavMeshSurface Icon", true); |
|||
} |
|||
|
|||
static void RenderBoxGizmo(NavMeshSurface navSurface, GizmoType gizmoType, bool selected) |
|||
{ |
|||
var color = selected ? s_HandleColorSelected : s_HandleColor; |
|||
if (!navSurface.enabled) |
|||
color = s_HandleColorDisabled; |
|||
|
|||
var oldColor = Gizmos.color; |
|||
var oldMatrix = Gizmos.matrix; |
|||
|
|||
// Use the unscaled matrix for the NavMeshSurface
|
|||
var localToWorld = Matrix4x4.TRS(navSurface.transform.position, navSurface.transform.rotation, Vector3.one); |
|||
Gizmos.matrix = localToWorld; |
|||
|
|||
if (navSurface.collectObjects == CollectObjects.Volume) |
|||
{ |
|||
Gizmos.color = color; |
|||
Gizmos.DrawWireCube(navSurface.center, navSurface.size); |
|||
|
|||
if (selected && navSurface.enabled) |
|||
{ |
|||
var colorTrans = new Color(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, color.a * 0.15f); |
|||
Gizmos.color = colorTrans; |
|||
Gizmos.DrawCube(navSurface.center, navSurface.size); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (navSurface.navMeshData != null) |
|||
{ |
|||
var bounds = navSurface.navMeshData.sourceBounds; |
|||
Gizmos.color = Color.grey; |
|||
Gizmos.DrawWireCube(bounds.center, bounds.size); |
|||
} |
|||
} |
|||
|
|||
Gizmos.matrix = oldMatrix; |
|||
Gizmos.color = oldColor; |
|||
|
|||
Gizmos.DrawIcon(navSurface.transform.position, "NavMeshSurface Icon", true); |
|||
} |
|||
|
|||
void OnSceneGUI() |
|||
{ |
|||
if (!editingCollider) |
|||
return; |
|||
|
|||
var navSurface = (NavMeshSurface)target; |
|||
var color = navSurface.enabled ? s_HandleColor : s_HandleColorDisabled; |
|||
var localToWorld = Matrix4x4.TRS(navSurface.transform.position, navSurface.transform.rotation, Vector3.one); |
|||
using (new Handles.DrawingScope(color, localToWorld)) |
|||
{ |
|||
m_BoundsHandle.center = navSurface.center; |
|||
m_BoundsHandle.size = navSurface.size; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_BoundsHandle.DrawHandle(); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
Undo.RecordObject(navSurface, "Modified NavMesh Surface"); |
|||
Vector3 center = m_BoundsHandle.center; |
|||
Vector3 size = m_BoundsHandle.size; |
|||
navSurface.center = center; |
|||
navSurface.size = size; |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[MenuItem("GameObject/AI/NavMesh Surface", false, 2000)] |
|||
public static void CreateNavMeshSurface(MenuCommand menuCommand) |
|||
{ |
|||
var parent = menuCommand.context as GameObject; |
|||
var go = NavMeshComponentsGUIUtility.CreateAndSelectGameObject("NavMesh Surface", parent); |
|||
go.AddComponent<NavMeshSurface>(); |
|||
var view = SceneView.lastActiveSceneView; |
|||
if (view != null) |
|||
view.MoveToView(go.transform); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1c32167dbf3314852b6006a288eb449b |
|||
timeCreated: 1476968447 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: ce67aa87f613246dda63a54a59c6399e |
|||
folderAsset: yes |
|||
timeCreated: 1477656493 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8c4dd21966739024fbd72155091d199e |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.AI |
|||
{ |
|||
[ExecuteInEditMode] |
|||
[DefaultExecutionOrder(-101)] |
|||
[AddComponentMenu("Navigation/NavMeshLink", 33)] |
|||
[HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")] |
|||
public class NavMeshLink : MonoBehaviour |
|||
{ |
|||
[SerializeField] |
|||
int m_AgentTypeID; |
|||
public int agentTypeID { get { return m_AgentTypeID; } set { m_AgentTypeID = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
Vector3 m_StartPoint = new Vector3(0.0f, 0.0f, -2.5f); |
|||
public Vector3 startPoint { get { return m_StartPoint; } set { m_StartPoint = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
Vector3 m_EndPoint = new Vector3(0.0f, 0.0f, 2.5f); |
|||
public Vector3 endPoint { get { return m_EndPoint; } set { m_EndPoint = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
float m_Width; |
|||
public float width { get { return m_Width; } set { m_Width = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
int m_CostModifier = -1; |
|||
public int costModifier { get { return m_CostModifier; } set { m_CostModifier = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
bool m_Bidirectional = true; |
|||
public bool bidirectional { get { return m_Bidirectional; } set { m_Bidirectional = value; UpdateLink(); } } |
|||
|
|||
[SerializeField] |
|||
bool m_AutoUpdatePosition; |
|||
public bool autoUpdate { get { return m_AutoUpdatePosition; } set { SetAutoUpdate(value); } } |
|||
|
|||
[SerializeField] |
|||
int m_Area; |
|||
public int area { get { return m_Area; } set { m_Area = value; UpdateLink(); } } |
|||
|
|||
NavMeshLinkInstance m_LinkInstance = new NavMeshLinkInstance(); |
|||
|
|||
Vector3 m_LastPosition = Vector3.zero; |
|||
Quaternion m_LastRotation = Quaternion.identity; |
|||
|
|||
static readonly List<NavMeshLink> s_Tracked = new List<NavMeshLink>(); |
|||
|
|||
void OnEnable() |
|||
{ |
|||
AddLink(); |
|||
if (m_AutoUpdatePosition && m_LinkInstance.valid) |
|||
AddTracking(this); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
RemoveTracking(this); |
|||
m_LinkInstance.Remove(); |
|||
} |
|||
|
|||
public void UpdateLink() |
|||
{ |
|||
m_LinkInstance.Remove(); |
|||
AddLink(); |
|||
} |
|||
|
|||
static void AddTracking(NavMeshLink link) |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
if (s_Tracked.Contains(link)) |
|||
{ |
|||
Debug.LogError("Link is already tracked: " + link); |
|||
return; |
|||
} |
|||
#endif
|
|||
|
|||
if (s_Tracked.Count == 0) |
|||
NavMesh.onPreUpdate += UpdateTrackedInstances; |
|||
|
|||
s_Tracked.Add(link); |
|||
} |
|||
|
|||
static void RemoveTracking(NavMeshLink link) |
|||
{ |
|||
s_Tracked.Remove(link); |
|||
|
|||
if (s_Tracked.Count == 0) |
|||
NavMesh.onPreUpdate -= UpdateTrackedInstances; |
|||
} |
|||
|
|||
void SetAutoUpdate(bool value) |
|||
{ |
|||
if (m_AutoUpdatePosition == value) |
|||
return; |
|||
m_AutoUpdatePosition = value; |
|||
if (value) |
|||
AddTracking(this); |
|||
else |
|||
RemoveTracking(this); |
|||
} |
|||
|
|||
void AddLink() |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
if (m_LinkInstance.valid) |
|||
{ |
|||
Debug.LogError("Link is already added: " + this); |
|||
return; |
|||
} |
|||
#endif
|
|||
|
|||
var link = new NavMeshLinkData(); |
|||
link.startPosition = m_StartPoint; |
|||
link.endPosition = m_EndPoint; |
|||
link.width = m_Width; |
|||
link.costModifier = m_CostModifier; |
|||
link.bidirectional = m_Bidirectional; |
|||
link.area = m_Area; |
|||
link.agentTypeID = m_AgentTypeID; |
|||
m_LinkInstance = NavMesh.AddLink(link, transform.position, transform.rotation); |
|||
if (m_LinkInstance.valid) |
|||
m_LinkInstance.owner = this; |
|||
|
|||
m_LastPosition = transform.position; |
|||
m_LastRotation = transform.rotation; |
|||
} |
|||
|
|||
bool HasTransformChanged() |
|||
{ |
|||
if (m_LastPosition != transform.position) return true; |
|||
if (m_LastRotation != transform.rotation) return true; |
|||
return false; |
|||
} |
|||
|
|||
void OnDidApplyAnimationProperties() |
|||
{ |
|||
UpdateLink(); |
|||
} |
|||
|
|||
static void UpdateTrackedInstances() |
|||
{ |
|||
foreach (var instance in s_Tracked) |
|||
{ |
|||
if (instance.HasTransformChanged()) |
|||
instance.UpdateLink(); |
|||
} |
|||
} |
|||
|
|||
#if UNITY_EDITOR
|
|||
void OnValidate() |
|||
{ |
|||
m_Width = Mathf.Max(0.0f, m_Width); |
|||
|
|||
if (!m_LinkInstance.valid) |
|||
return; |
|||
|
|||
UpdateLink(); |
|||
|
|||
if (!m_AutoUpdatePosition) |
|||
{ |
|||
RemoveTracking(this); |
|||
} |
|||
else if (!s_Tracked.Contains(this)) |
|||
{ |
|||
AddTracking(this); |
|||
} |
|||
} |
|||
#endif
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6eeb5dc026fdf4b488bc7ae0138ab719 |
|||
timeCreated: 1477924439 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {fileID: 2800000, guid: 92f4afa3e25264f5b964937ccea49ff2, type: 3} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.AI |
|||
{ |
|||
[ExecuteInEditMode] |
|||
[AddComponentMenu("Navigation/NavMeshModifier", 32)] |
|||
[HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")] |
|||
public class NavMeshModifier : MonoBehaviour |
|||
{ |
|||
[SerializeField] |
|||
bool m_OverrideArea; |
|||
public bool overrideArea { get { return m_OverrideArea; } set { m_OverrideArea = value; } } |
|||
|
|||
[SerializeField] |
|||
int m_Area; |
|||
public int area { get { return m_Area; } set { m_Area = value; } } |
|||
|
|||
[SerializeField] |
|||
bool m_IgnoreFromBuild; |
|||
public bool ignoreFromBuild { get { return m_IgnoreFromBuild; } set { m_IgnoreFromBuild = value; } } |
|||
|
|||
// List of agent types the modifier is applied for.
|
|||
// Special values: empty == None, m_AffectedAgents[0] =-1 == All.
|
|||
[SerializeField] |
|||
List<int> m_AffectedAgents = new List<int>(new int[] { -1 }); // Default value is All
|
|||
|
|||
static readonly List<NavMeshModifier> s_NavMeshModifiers = new List<NavMeshModifier>(); |
|||
|
|||
public static List<NavMeshModifier> activeModifiers |
|||
{ |
|||
get { return s_NavMeshModifiers; } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
if (!s_NavMeshModifiers.Contains(this)) |
|||
s_NavMeshModifiers.Add(this); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
s_NavMeshModifiers.Remove(this); |
|||
} |
|||
|
|||
public bool AffectsAgentType(int agentTypeID) |
|||
{ |
|||
if (m_AffectedAgents.Count == 0) |
|||
return false; |
|||
if (m_AffectedAgents[0] == -1) |
|||
return true; |
|||
return m_AffectedAgents.IndexOf(agentTypeID) != -1; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1e3fdca004f2d45fe8abbed571a8abd5 |
|||
timeCreated: 1477924411 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {fileID: 2800000, guid: cc7b9475dbddf4f9088d327d6e10ab77, type: 3} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.AI |
|||
{ |
|||
[ExecuteInEditMode] |
|||
[AddComponentMenu("Navigation/NavMeshModifierVolume", 31)] |
|||
[HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")] |
|||
public class NavMeshModifierVolume : MonoBehaviour |
|||
{ |
|||
[SerializeField] |
|||
Vector3 m_Size = new Vector3(4.0f, 3.0f, 4.0f); |
|||
public Vector3 size { get { return m_Size; } set { m_Size = value; } } |
|||
|
|||
[SerializeField] |
|||
Vector3 m_Center = new Vector3(0, 1.0f, 0); |
|||
public Vector3 center { get { return m_Center; } set { m_Center = value; } } |
|||
|
|||
[SerializeField] |
|||
int m_Area; |
|||
public int area { get { return m_Area; } set { m_Area = value; } } |
|||
|
|||
// List of agent types the modifier is applied for.
|
|||
// Special values: empty == None, m_AffectedAgents[0] =-1 == All.
|
|||
[SerializeField] |
|||
List<int> m_AffectedAgents = new List<int>(new int[] { -1 }); // Default value is All
|
|||
|
|||
static readonly List<NavMeshModifierVolume> s_NavMeshModifiers = new List<NavMeshModifierVolume>(); |
|||
|
|||
public static List<NavMeshModifierVolume> activeModifiers |
|||
{ |
|||
get { return s_NavMeshModifiers; } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
if (!s_NavMeshModifiers.Contains(this)) |
|||
s_NavMeshModifiers.Add(this); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
s_NavMeshModifiers.Remove(this); |
|||
} |
|||
|
|||
public bool AffectsAgentType(int agentTypeID) |
|||
{ |
|||
if (m_AffectedAgents.Count == 0) |
|||
return false; |
|||
if (m_AffectedAgents[0] == -1) |
|||
return true; |
|||
return m_AffectedAgents.IndexOf(agentTypeID) != -1; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 35e95dc5ff2b64380880dd7ac5922847 |
|||
timeCreated: 1477924430 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {fileID: 2800000, guid: cc7b9475dbddf4f9088d327d6e10ab77, type: 3} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
#if UNITY_EDITOR
|
|||
using UnityEditor; |
|||
using UnityEditor.SceneManagement; |
|||
#endif
|
|||
|
|||
namespace UnityEngine.AI |
|||
{ |
|||
public enum CollectObjects |
|||
{ |
|||
All = 0, |
|||
Volume = 1, |
|||
Children = 2, |
|||
} |
|||
|
|||
[ExecuteAlways] |
|||
[DefaultExecutionOrder(-102)] |
|||
[AddComponentMenu("Navigation/NavMeshSurface", 30)] |
|||
[HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")] |
|||
public class NavMeshSurface : MonoBehaviour |
|||
{ |
|||
[SerializeField] |
|||
int m_AgentTypeID; |
|||
public int agentTypeID { get { return m_AgentTypeID; } set { m_AgentTypeID = value; } } |
|||
|
|||
[SerializeField] |
|||
CollectObjects m_CollectObjects = CollectObjects.All; |
|||
public CollectObjects collectObjects { get { return m_CollectObjects; } set { m_CollectObjects = value; } } |
|||
|
|||
[SerializeField] |
|||
Vector3 m_Size = new Vector3(10.0f, 10.0f, 10.0f); |
|||
public Vector3 size { get { return m_Size; } set { m_Size = value; } } |
|||
|
|||
[SerializeField] |
|||
Vector3 m_Center = new Vector3(0, 2.0f, 0); |
|||
public Vector3 center { get { return m_Center; } set { m_Center = value; } } |
|||
|
|||
[SerializeField] |
|||
LayerMask m_LayerMask = ~0; |
|||
public LayerMask layerMask { get { return m_LayerMask; } set { m_LayerMask = value; } } |
|||
|
|||
[SerializeField] |
|||
NavMeshCollectGeometry m_UseGeometry = NavMeshCollectGeometry.RenderMeshes; |
|||
public NavMeshCollectGeometry useGeometry { get { return m_UseGeometry; } set { m_UseGeometry = value; } } |
|||
|
|||
[SerializeField] |
|||
int m_DefaultArea; |
|||
public int defaultArea { get { return m_DefaultArea; } set { m_DefaultArea = value; } } |
|||
|
|||
[SerializeField] |
|||
bool m_IgnoreNavMeshAgent = true; |
|||
public bool ignoreNavMeshAgent { get { return m_IgnoreNavMeshAgent; } set { m_IgnoreNavMeshAgent = value; } } |
|||
|
|||
[SerializeField] |
|||
bool m_IgnoreNavMeshObstacle = true; |
|||
public bool ignoreNavMeshObstacle { get { return m_IgnoreNavMeshObstacle; } set { m_IgnoreNavMeshObstacle = value; } } |
|||
|
|||
[SerializeField] |
|||
bool m_OverrideTileSize; |
|||
public bool overrideTileSize { get { return m_OverrideTileSize; } set { m_OverrideTileSize = value; } } |
|||
[SerializeField] |
|||
int m_TileSize = 256; |
|||
public int tileSize { get { return m_TileSize; } set { m_TileSize = value; } } |
|||
[SerializeField] |
|||
bool m_OverrideVoxelSize; |
|||
public bool overrideVoxelSize { get { return m_OverrideVoxelSize; } set { m_OverrideVoxelSize = value; } } |
|||
[SerializeField] |
|||
float m_VoxelSize; |
|||
public float voxelSize { get { return m_VoxelSize; } set { m_VoxelSize = value; } } |
|||
|
|||
// Currently not supported advanced options
|
|||
[SerializeField] |
|||
bool m_BuildHeightMesh; |
|||
public bool buildHeightMesh { get { return m_BuildHeightMesh; } set { m_BuildHeightMesh = value; } } |
|||
|
|||
// Reference to whole scene navmesh data asset.
|
|||
[UnityEngine.Serialization.FormerlySerializedAs("m_BakedNavMeshData")] |
|||
[SerializeField] |
|||
NavMeshData m_NavMeshData; |
|||
public NavMeshData navMeshData { get { return m_NavMeshData; } set { m_NavMeshData = value; } } |
|||
|
|||
// Do not serialize - runtime only state.
|
|||
NavMeshDataInstance m_NavMeshDataInstance; |
|||
Vector3 m_LastPosition = Vector3.zero; |
|||
Quaternion m_LastRotation = Quaternion.identity; |
|||
|
|||
static readonly List<NavMeshSurface> s_NavMeshSurfaces = new List<NavMeshSurface>(); |
|||
|
|||
public static List<NavMeshSurface> activeSurfaces |
|||
{ |
|||
get { return s_NavMeshSurfaces; } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
Register(this); |
|||
AddData(); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
RemoveData(); |
|||
Unregister(this); |
|||
} |
|||
|
|||
public void AddData() |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
var isInPreviewScene = EditorSceneManager.IsPreviewSceneObject(this); |
|||
var isPrefab = isInPreviewScene || EditorUtility.IsPersistent(this); |
|||
if (isPrefab) |
|||
{ |
|||
//Debug.LogFormat("NavMeshData from {0}.{1} will not be added to the NavMesh world because the gameObject is a prefab.",
|
|||
// gameObject.name, name);
|
|||
return; |
|||
} |
|||
#endif
|
|||
if (m_NavMeshDataInstance.valid) |
|||
return; |
|||
|
|||
if (m_NavMeshData != null) |
|||
{ |
|||
m_NavMeshDataInstance = NavMesh.AddNavMeshData(m_NavMeshData, transform.position, transform.rotation); |
|||
m_NavMeshDataInstance.owner = this; |
|||
} |
|||
|
|||
m_LastPosition = transform.position; |
|||
m_LastRotation = transform.rotation; |
|||
} |
|||
|
|||
public void RemoveData() |
|||
{ |
|||
m_NavMeshDataInstance.Remove(); |
|||
m_NavMeshDataInstance = new NavMeshDataInstance(); |
|||
} |
|||
|
|||
public NavMeshBuildSettings GetBuildSettings() |
|||
{ |
|||
var buildSettings = NavMesh.GetSettingsByID(m_AgentTypeID); |
|||
if (buildSettings.agentTypeID == -1) |
|||
{ |
|||
Debug.LogWarning("No build settings for agent type ID " + agentTypeID, this); |
|||
buildSettings.agentTypeID = m_AgentTypeID; |
|||
} |
|||
|
|||
if (overrideTileSize) |
|||
{ |
|||
buildSettings.overrideTileSize = true; |
|||
buildSettings.tileSize = tileSize; |
|||
} |
|||
if (overrideVoxelSize) |
|||
{ |
|||
buildSettings.overrideVoxelSize = true; |
|||
buildSettings.voxelSize = voxelSize; |
|||
} |
|||
return buildSettings; |
|||
} |
|||
|
|||
public void BuildNavMesh() |
|||
{ |
|||
var sources = CollectSources(); |
|||
|
|||
// Use unscaled bounds - this differs in behaviour from e.g. collider components.
|
|||
// But is similar to reflection probe - and since navmesh data has no scaling support - it is the right choice here.
|
|||
var sourcesBounds = new Bounds(m_Center, Abs(m_Size)); |
|||
if (m_CollectObjects == CollectObjects.All || m_CollectObjects == CollectObjects.Children) |
|||
{ |
|||
sourcesBounds = CalculateWorldBounds(sources); |
|||
} |
|||
|
|||
var data = NavMeshBuilder.BuildNavMeshData(GetBuildSettings(), |
|||
sources, sourcesBounds, transform.position, transform.rotation); |
|||
|
|||
if (data != null) |
|||
{ |
|||
data.name = gameObject.name; |
|||
RemoveData(); |
|||
m_NavMeshData = data; |
|||
if (isActiveAndEnabled) |
|||
AddData(); |
|||
} |
|||
} |
|||
|
|||
public AsyncOperation UpdateNavMesh(NavMeshData data) |
|||
{ |
|||
var sources = CollectSources(); |
|||
|
|||
// Use unscaled bounds - this differs in behaviour from e.g. collider components.
|
|||
// But is similar to reflection probe - and since navmesh data has no scaling support - it is the right choice here.
|
|||
var sourcesBounds = new Bounds(m_Center, Abs(m_Size)); |
|||
if (m_CollectObjects == CollectObjects.All || m_CollectObjects == CollectObjects.Children) |
|||
sourcesBounds = CalculateWorldBounds(sources); |
|||
|
|||
return NavMeshBuilder.UpdateNavMeshDataAsync(data, GetBuildSettings(), sources, sourcesBounds); |
|||
} |
|||
|
|||
static void Register(NavMeshSurface surface) |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
var isInPreviewScene = EditorSceneManager.IsPreviewSceneObject(surface); |
|||
var isPrefab = isInPreviewScene || EditorUtility.IsPersistent(surface); |
|||
if (isPrefab) |
|||
{ |
|||
//Debug.LogFormat("NavMeshData from {0}.{1} will not be added to the NavMesh world because the gameObject is a prefab.",
|
|||
// surface.gameObject.name, surface.name);
|
|||
return; |
|||
} |
|||
#endif
|
|||
if (s_NavMeshSurfaces.Count == 0) |
|||
NavMesh.onPreUpdate += UpdateActive; |
|||
|
|||
if (!s_NavMeshSurfaces.Contains(surface)) |
|||
s_NavMeshSurfaces.Add(surface); |
|||
} |
|||
|
|||
static void Unregister(NavMeshSurface surface) |
|||
{ |
|||
s_NavMeshSurfaces.Remove(surface); |
|||
|
|||
if (s_NavMeshSurfaces.Count == 0) |
|||
NavMesh.onPreUpdate -= UpdateActive; |
|||
} |
|||
|
|||
static void UpdateActive() |
|||
{ |
|||
for (var i = 0; i < s_NavMeshSurfaces.Count; ++i) |
|||
s_NavMeshSurfaces[i].UpdateDataIfTransformChanged(); |
|||
} |
|||
|
|||
void AppendModifierVolumes(ref List<NavMeshBuildSource> sources) |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
var myStage = StageUtility.GetStageHandle(gameObject); |
|||
if (!myStage.IsValid()) |
|||
return; |
|||
#endif
|
|||
// Modifiers
|
|||
List<NavMeshModifierVolume> modifiers; |
|||
if (m_CollectObjects == CollectObjects.Children) |
|||
{ |
|||
modifiers = new List<NavMeshModifierVolume>(GetComponentsInChildren<NavMeshModifierVolume>()); |
|||
modifiers.RemoveAll(x => !x.isActiveAndEnabled); |
|||
} |
|||
else |
|||
{ |
|||
modifiers = NavMeshModifierVolume.activeModifiers; |
|||
} |
|||
|
|||
foreach (var m in modifiers) |
|||
{ |
|||
if ((m_LayerMask & (1 << m.gameObject.layer)) == 0) |
|||
continue; |
|||
if (!m.AffectsAgentType(m_AgentTypeID)) |
|||
continue; |
|||
#if UNITY_EDITOR
|
|||
if (!myStage.Contains(m.gameObject)) |
|||
continue; |
|||
#endif
|
|||
var mcenter = m.transform.TransformPoint(m.center); |
|||
var scale = m.transform.lossyScale; |
|||
var msize = new Vector3(m.size.x * Mathf.Abs(scale.x), m.size.y * Mathf.Abs(scale.y), m.size.z * Mathf.Abs(scale.z)); |
|||
|
|||
var src = new NavMeshBuildSource(); |
|||
src.shape = NavMeshBuildSourceShape.ModifierBox; |
|||
src.transform = Matrix4x4.TRS(mcenter, m.transform.rotation, Vector3.one); |
|||
src.size = msize; |
|||
src.area = m.area; |
|||
sources.Add(src); |
|||
} |
|||
} |
|||
|
|||
List<NavMeshBuildSource> CollectSources() |
|||
{ |
|||
var sources = new List<NavMeshBuildSource>(); |
|||
var markups = new List<NavMeshBuildMarkup>(); |
|||
|
|||
List<NavMeshModifier> modifiers; |
|||
if (m_CollectObjects == CollectObjects.Children) |
|||
{ |
|||
modifiers = new List<NavMeshModifier>(GetComponentsInChildren<NavMeshModifier>()); |
|||
modifiers.RemoveAll(x => !x.isActiveAndEnabled); |
|||
} |
|||
else |
|||
{ |
|||
modifiers = NavMeshModifier.activeModifiers; |
|||
} |
|||
|
|||
foreach (var m in modifiers) |
|||
{ |
|||
if ((m_LayerMask & (1 << m.gameObject.layer)) == 0) |
|||
continue; |
|||
if (!m.AffectsAgentType(m_AgentTypeID)) |
|||
continue; |
|||
var markup = new NavMeshBuildMarkup(); |
|||
markup.root = m.transform; |
|||
markup.overrideArea = m.overrideArea; |
|||
markup.area = m.area; |
|||
markup.ignoreFromBuild = m.ignoreFromBuild; |
|||
markups.Add(markup); |
|||
} |
|||
|
|||
#if UNITY_EDITOR
|
|||
if (!EditorApplication.isPlaying) |
|||
{ |
|||
if (m_CollectObjects == CollectObjects.All) |
|||
{ |
|||
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage( |
|||
null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources); |
|||
} |
|||
else if (m_CollectObjects == CollectObjects.Children) |
|||
{ |
|||
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage( |
|||
transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources); |
|||
} |
|||
else if (m_CollectObjects == CollectObjects.Volume) |
|||
{ |
|||
Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); |
|||
var worldBounds = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size)); |
|||
|
|||
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage( |
|||
worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources); |
|||
} |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
if (m_CollectObjects == CollectObjects.All) |
|||
{ |
|||
NavMeshBuilder.CollectSources(null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources); |
|||
} |
|||
else if (m_CollectObjects == CollectObjects.Children) |
|||
{ |
|||
NavMeshBuilder.CollectSources(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources); |
|||
} |
|||
else if (m_CollectObjects == CollectObjects.Volume) |
|||
{ |
|||
Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); |
|||
var worldBounds = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size)); |
|||
NavMeshBuilder.CollectSources(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources); |
|||
} |
|||
} |
|||
|
|||
if (m_IgnoreNavMeshAgent) |
|||
sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null)); |
|||
|
|||
if (m_IgnoreNavMeshObstacle) |
|||
sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null)); |
|||
|
|||
AppendModifierVolumes(ref sources); |
|||
|
|||
return sources; |
|||
} |
|||
|
|||
static Vector3 Abs(Vector3 v) |
|||
{ |
|||
return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z)); |
|||
} |
|||
|
|||
static Bounds GetWorldBounds(Matrix4x4 mat, Bounds bounds) |
|||
{ |
|||
var absAxisX = Abs(mat.MultiplyVector(Vector3.right)); |
|||
var absAxisY = Abs(mat.MultiplyVector(Vector3.up)); |
|||
var absAxisZ = Abs(mat.MultiplyVector(Vector3.forward)); |
|||
var worldPosition = mat.MultiplyPoint(bounds.center); |
|||
var worldSize = absAxisX * bounds.size.x + absAxisY * bounds.size.y + absAxisZ * bounds.size.z; |
|||
return new Bounds(worldPosition, worldSize); |
|||
} |
|||
|
|||
Bounds CalculateWorldBounds(List<NavMeshBuildSource> sources) |
|||
{ |
|||
// Use the unscaled matrix for the NavMeshSurface
|
|||
Matrix4x4 worldToLocal = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); |
|||
worldToLocal = worldToLocal.inverse; |
|||
|
|||
var result = new Bounds(); |
|||
foreach (var src in sources) |
|||
{ |
|||
switch (src.shape) |
|||
{ |
|||
case NavMeshBuildSourceShape.Mesh: |
|||
{ |
|||
var m = src.sourceObject as Mesh; |
|||
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, m.bounds)); |
|||
break; |
|||
} |
|||
case NavMeshBuildSourceShape.Terrain: |
|||
{ |
|||
// Terrain pivot is lower/left corner - shift bounds accordingly
|
|||
var t = src.sourceObject as TerrainData; |
|||
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, new Bounds(0.5f * t.size, t.size))); |
|||
break; |
|||
} |
|||
case NavMeshBuildSourceShape.Box: |
|||
case NavMeshBuildSourceShape.Sphere: |
|||
case NavMeshBuildSourceShape.Capsule: |
|||
case NavMeshBuildSourceShape.ModifierBox: |
|||
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, new Bounds(Vector3.zero, src.size))); |
|||
break; |
|||
} |
|||
} |
|||
// Inflate the bounds a bit to avoid clipping co-planar sources
|
|||
result.Expand(0.1f); |
|||
return result; |
|||
} |
|||
|
|||
bool HasTransformChanged() |
|||
{ |
|||
if (m_LastPosition != transform.position) return true; |
|||
if (m_LastRotation != transform.rotation) return true; |
|||
return false; |
|||
} |
|||
|
|||
void UpdateDataIfTransformChanged() |
|||
{ |
|||
if (HasTransformChanged()) |
|||
{ |
|||
RemoveData(); |
|||
AddData(); |
|||
} |
|||
} |
|||
|
|||
#if UNITY_EDITOR
|
|||
bool UnshareNavMeshAsset() |
|||
{ |
|||
// Nothing to unshare
|
|||
if (m_NavMeshData == null) |
|||
return false; |
|||
|
|||
// Prefab parent owns the asset reference
|
|||
var isInPreviewScene = EditorSceneManager.IsPreviewSceneObject(this); |
|||
var isPersistentObject = EditorUtility.IsPersistent(this); |
|||
if (isInPreviewScene || isPersistentObject) |
|||
return false; |
|||
|
|||
// An instance can share asset reference only with its prefab parent
|
|||
var prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(this) as NavMeshSurface; |
|||
if (prefab != null && prefab.navMeshData == navMeshData) |
|||
return false; |
|||
|
|||
// Don't allow referencing an asset that's assigned to another surface
|
|||
for (var i = 0; i < s_NavMeshSurfaces.Count; ++i) |
|||
{ |
|||
var surface = s_NavMeshSurfaces[i]; |
|||
if (surface != this && surface.m_NavMeshData == m_NavMeshData) |
|||
return true; |
|||
} |
|||
|
|||
// Asset is not referenced by known surfaces
|
|||
return false; |
|||
} |
|||
|
|||
void OnValidate() |
|||
{ |
|||
if (UnshareNavMeshAsset()) |
|||
{ |
|||
Debug.LogWarning("Duplicating NavMeshSurface does not duplicate the referenced navmesh data", this); |
|||
m_NavMeshData = null; |
|||
} |
|||
|
|||
var settings = NavMesh.GetSettingsByID(m_AgentTypeID); |
|||
if (settings.agentTypeID != -1) |
|||
{ |
|||
// When unchecking the override control, revert to automatic value.
|
|||
const float kMinVoxelSize = 0.01f; |
|||
if (!m_OverrideVoxelSize) |
|||
m_VoxelSize = settings.agentRadius / 3.0f; |
|||
if (m_VoxelSize < kMinVoxelSize) |
|||
m_VoxelSize = kMinVoxelSize; |
|||
|
|||
// When unchecking the override control, revert to default value.
|
|||
const int kMinTileSize = 16; |
|||
const int kMaxTileSize = 1024; |
|||
const int kDefaultTileSize = 256; |
|||
|
|||
if (!m_OverrideTileSize) |
|||
m_TileSize = kDefaultTileSize; |
|||
// Make sure tilesize is in sane range.
|
|||
if (m_TileSize < kMinTileSize) |
|||
m_TileSize = kMinTileSize; |
|||
if (m_TileSize > kMaxTileSize) |
|||
m_TileSize = kMaxTileSize; |
|||
} |
|||
} |
|||
#endif
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7a5ac11cc976e418e8d13136b07e1f52 |
|||
timeCreated: 1477658803 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {fileID: 2800000, guid: e4f97225bcfb64760a1c81f460837f01, type: 3} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
38
Assets/Shaders/Graphs/CliffShader.ShaderGraph
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
47
Assets/Shaders/Graphs/PBR_HUE.ShaderGraph
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
4
Assets/Shaders/Graphs/Vegetation.shadergraph
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
823
Assets/scenes/Island.unity
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
6
Assets/scenes/Island/LightingData.asset
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
983
Assets/scenes/Island/MainIsland.asset
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
v/1 channels chlist 7 B G R compression compression dataWindow box2i ? displayWindow box2i ? lineOrder lineOrder pixelAspectRatio float �?screenWindowCenter v2f screenWindowWidth float �? I �� v� � ��@@@ � @@@� @�@� � � @@, � � �A � ` ! �1 �`��CK�X� 4%0*�̏�J�����&�� |
|||
�FEt�rr��0P�"T�U6.�/o�®�Z����Z��
��<'��LۈbL���;�[N?���s;�J]�u?�ս�c�[������?���wE��~����]��������������������������������w��u���������|������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������^�����{�����������������~˿�ػ����W��͇b~�u��O�'6�1�o�ܤ���9�P�y���&N�࿚���$A��҆�� �+����<�PE2����! |
|||
� Ę�D0`'�o�@NwX�tfw�(B�E�_iy���]\�~m�9�M��~��c�����S����A����������s�=[�ψ���ބ;!����#�H*��/�Z#��R�Cw��D` �(�n8����tS�Eʙ7H�$�H@!��Q�چ
���e��EF* J���nV |
|||
e�9H�V�#�����������������������������������������������߯������߿���w�?{�������������������������������������������������G�{��wo��y���������;�a���_���k��=B�������!Z�4pD�`��bwFk`��e�� C �J " |