void GenerateLinks(NavLinkGenerator gen) { var tri = NavMesh.CalculateTriangulation(); var edge_list = CreateEdges(tri); foreach (var edge in edge_list) { edge.ComputeDerivedData(); } if (edge_list.Count() == 0) { return; } RemoveLinks(); m_CreatedLinks.Clear(); var parent = NavEdUtil.GetNamedRoot(k_LinkRootName); foreach (var edge in edge_list) { var mid = edge.GetMidpoint(); var fwd = edge.m_Normal; var link = CreateNavLink(parent, gen, edge, mid, fwd); if (link != null) { m_CreatedLinks.Add(link); } } }
void RemoveLinks() { var nav_links = NavEdUtil.GetNamedRoot(k_LinkRootName).GetComponentsInChildren <NavMeshLink>(); foreach (var link in nav_links) { GameObject.DestroyImmediate(link.gameObject); } }
static void CreateNonWalkableVolumes(NavNonWalkableCollection collection) { if (collection.m_Volumes == null) { collection.m_Volumes = new List <NavMeshModifierVolume>(); } ClearVolumes(collection); var surfaces = NavEdUtil.GetAllInActiveScene <NavMeshSurface>(); var colliders = surfaces .SelectMany(s => (s as NavMeshSurface).GetComponentsInChildren <Collider>()); var threshold_sqr = 1.5f * 1.5f; foreach (Collider c in colliders) { if (c.GetComponentInChildren <NavMeshModifierVolume>() != null) { // Skip so we can move them out of m_Volumes to make them persistent. Debug.Log($"[NavMesh] Skipping NonWalkable generation on {c.name} because it already has a NavMeshModifierVolume child.", c); continue; } // Get unrotated bounds. Hopefully these are tighter. var t = c.transform; var rot = t.rotation; var pos = t.position; t.position = Vector3.zero; t.rotation = Quaternion.identity; Physics.SyncTransforms(); var b = c.bounds; t.rotation = rot; t.position = pos; if (b.size.sqrMagnitude > threshold_sqr) { var obj = new GameObject("Block NavMesh - " + t.name); obj.transform.SetParent(t); obj.transform.SetPositionAndRotation(pos, rot); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; var vol = obj.AddComponent <NavMeshModifierVolume>(); vol.area = (int)NavMeshAreaIndex.NotWalkable; var offset = 0.2f; var size = b.size; size -= Vector3.one * offset; vol.size = size; vol.center = b.center + Vector3.down * offset; Undo.RegisterCreatedObjectUndo(obj, "Create No Walk Volumes"); collection.m_Volumes.Add(vol); } } Undo.RecordObject(collection, "Create No Walk Volumes"); }
static NavNonWalkableCollection Get() { var root = NavEdUtil.GetNamedRoot(k_NoMeshVolumeRootName); if (root == null) { root = new GameObject(k_NoMeshVolumeRootName).transform; } var collection = root.GetComponent <NavNonWalkableCollection>(); if (collection == null) { collection = root.gameObject.AddComponent <NavNonWalkableCollection>(); } return(collection); }
public override void OnInspectorGUI() { DrawDefaultInspector(); var collection = target as NavNonWalkableCollection; using (new GUILayout.HorizontalScope()) { if (GUILayout.Button("Clear Interior Volumes")) { ClearVolumes(collection); } if (GUILayout.Button("Create Interior Volumes")) { CreateNonWalkableVolumes(collection); } if (GUILayout.Button("Select NavMesh")) { Selection.objects = NavEdUtil.GetAllInActiveScene <NavMeshSurface>(); } } }
public override void OnInspectorGUI() { DrawDefaultInspector(); var gen = target as NavLinkGenerator; m_AttachDebugToLinks = EditorGUILayout.Toggle("Attach Debug To Links", m_AttachDebugToLinks); EditorGUILayout.HelpBox("Workflow: click these buttons from left to right. See tooltips for more info.", MessageType.None); using (new GUILayout.HorizontalScope()) { if (GUILayout.Button(new GUIContent("Clear All", "Delete generated Interior Volumes, NavMesh, and NavMeshLinks."))) { NavNonWalkableCollection_Editor.ClearNonWalkableVolumes(); NavMeshAssetManager.instance.ClearSurfaces(NavEdUtil.GetAllInActiveScene <NavMeshSurface>()); RemoveLinks(); SceneView.RepaintAll(); Debug.Log($"Removed NavMesh and NavMeshLinks from all NavMeshSurfaces."); } if (GUILayout.Button(new GUIContent("Create Interior Volumes", "Create NonWalkable volumes to prevent navmesh generation inside of solid objects."))) { NavNonWalkableCollection_Editor.CreateNonWalkableVolumes(); } if (GUILayout.Button(new GUIContent("Bake NavMesh", "Build navmesh for all NavMeshSurface."))) { var surfaces = NavEdUtil.GetAllInActiveScene <NavMeshSurface>(); NavMeshAssetManager.instance.StartBakingSurfaces(surfaces); Debug.Log($"Baked NavMesh for {surfaces.Length} NavMeshSurfaces."); } if (GUILayout.Button(new GUIContent("Bake Links", "Create NavMeshLinks along your navmesh edges."))) { GenerateLinks(gen); Debug.Log($"Baked NavMeshLinks."); } if (GUILayout.Button(new GUIContent("Select NavMesh", "Selecting the navmesh makes it draw in the Scene view so you can evaluate the quality of the mesh and the links."))) { Selection.objects = NavEdUtil.GetAllInActiveScene <NavMeshSurface>(); } } EditorGUILayout.Space(); m_ShowCreatedLinks = EditorGUILayout.Foldout(m_ShowCreatedLinks, "Created Links", toggleOnLabelClick: true); if (m_ShowCreatedLinks) { foreach (var entry in m_CreatedLinks) { using (new GUILayout.HorizontalScope()) { EditorGUILayout.ObjectField(entry, typeof(NavMeshLink), allowSceneObjects: true); using (new EditorGUI.DisabledScope(!m_AttachDebugToLinks)) { if (GUILayout.Button("Draw")) { entry.GetComponent <NavLinkCreationReason>().Draw(); if (SceneView.lastActiveSceneView != null) { // Prevent losing focus (we'd lose our state). ActiveEditorTracker.sharedTracker.isLocked = true; var activeGameObject = Selection.activeGameObject; activeGameObject = entry.gameObject; EditorGUIUtility.PingObject(activeGameObject); SceneView.lastActiveSceneView.FrameSelected(); Selection.activeGameObject = activeGameObject; } } } } } } }