public override void OnInspectorGUI() { base.OnInspectorGUI(); var bs = NavMesh.GetSettingsByID(m_AgentTypeID.intValue); serializedObject.Update(); 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); serializedObject.ApplyModifiedProperties(); }
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(); }
public override void OnInspectorGUI() { 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); } AgentTypePopup("Agent Type", m_AgentTypeID); EditorGUILayout.PropertyField(m_LayerMask, LayerMaskContent); EditorGUILayout.PropertyField(m_UseGeometry); }
void DrawProperties() { serializedObject.Update(); var bs = NavMesh.GetSettingsByID(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", agentTypeID); EditorGUILayout.Space(); NavMeshComponentsGUIUtility.AreaPopup("Default Area", defaultArea); EditorGUILayout.PropertyField(layerMask); EditorGUILayout.PropertyField(useGeometry); serializedObject.ApplyModifiedProperties(); }
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(); }
void OnGUI() { GUILayout.BeginVertical(); // colored logo //var backup = GUI.backgroundColor; //GUI.backgroundColor = Color.white; //GUILayout.BeginVertical("box"); GUILayout.Label(logo, new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter }); //GUILayout.EndVertical(); //GUI.backgroundColor = backup; GUILayout.Label("<b>by noobtuts.com</b>", new GUIStyle(GUI.skin.label) { richText = true, alignment = TextAnchor.MiddleCenter }); // instructions EditorGUILayout.Space(); EditorGUILayout.LabelField("Instructions", EditorStyles.boldLabel); EditorGUILayout.HelpBox(@"1. Make your 2D Colliders Static 2. Press Bake and wait until it's done 3. Add NavMeshAgent2D to agents", MessageType.Info); EditorGUILayout.Space(); // get access to original navigation settings // (that's how Unity's Navigation window does it too) var settings = new SerializedObject(UnityEditor.AI.NavMeshBuilder.navMeshSettingsObject); SerializedProperty agentRadius = settings.FindProperty("m_BuildSettings.agentRadius"); SerializedProperty agentHeight = settings.FindProperty("m_BuildSettings.agentHeight"); // settings header EditorGUILayout.Space(); EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); // diagram Rect controlRect = EditorGUILayout.GetControlRect(false, 120f, new GUILayoutOption[0]); NavMeshEditorHelpers.DrawAgentDiagram(controlRect, agentRadius.floatValue, agentHeight.floatValue, 0, 0); // agent radius agentRadius.floatValue = EditorGUILayout.FloatField(new GUIContent("Agent Radius", "Modifies the built in Agent Radius from Window->Navigation"), agentRadius.floatValue); settings.ApplyModifiedProperties(); // ground extends navmeshExtends = EditorGUILayout.Slider(new GUIContent("NavMesh Extends", "Can be used to cover the outside of your scene with a NavMesh"), navmeshExtends, 1, 100); // visibility drawMode = EditorGUILayout.IntPopup("Mode", drawMode, new string[] { "Wireframe", "Full" }, new int[] { 0, 1, 2 }); // repaint scene if drawMode option changed if (GUI.changed) { SceneView.RepaintAll(); } // buttons EditorGUILayout.Space(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Clear", GUILayout.Width(95f))) { UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes(); if (gizmesh != null) { gizmesh.Clear(); } } if (UnityEditor.AI.NavMeshBuilder.isRunning) { if (GUILayout.Button("Cancel", GUILayout.Width(95f))) { UnityEditor.AI.NavMeshBuilder.Cancel(); } } else { if (GUILayout.Button("Bake", GUILayout.Width(95f))) { BakeNavMesh2D(); } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
public override void OnInspectorGUI() { 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); } AgentTypePopup("Agent Type", m_AgentTypeID); EditorGUILayout.Space(); EditorGUILayout.PropertyField(m_LayerMask); EditorGUILayout.Space(); EditorGUILayout.Space(); m_OverrideVoxelSize.isExpanded = EditorGUILayout.Foldout(m_OverrideVoxelSize.isExpanded, "Advanced"); if (m_OverrideVoxelSize.isExpanded) { EditorGUI.indentLevel++; 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 in overal.", MessageType.None); } } EditorGUI.indentLevel--; } // Height mesh using (new EditorGUI.DisabledScope(true)) { EditorGUILayout.PropertyField(m_BuildHeightMesh); } EditorGUILayout.Space(); EditorGUI.indentLevel--; } EditorGUILayout.Space(); EditorGUILayout.PropertyField(m_Sprite); EditorGUILayout.PropertyField(m_NavMeshData); EditorGUILayout.PropertyField(m_Detail); EditorGUILayout.PropertyField(m_Color); if (GUILayout.Button("Regenerate NavMesh", GUILayout.Height(50))) { RegenerateMesh(); } serializedObject.ApplyModifiedProperties(); }
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++; InspectorEditButtonGUI(); EditorGUILayout.PropertyField(m_Size); EditorGUILayout.PropertyField(m_Center); } else { if (editingCollider) { EditMode.QuitEditMode(); } } EditorGUILayout.PropertyField(m_LayerMask, s_Styles.m_LayerMask); EditorGUILayout.PropertyField(m_UseGeometry); EditorGUILayout.Space(); 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 in overal.", 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(); } using (new EditorGUI.DisabledScope(Application.isPlaying || m_AgentTypeID.intValue == -1)) { GUILayout.BeginHorizontal(); GUILayout.Space(EditorGUIUtility.labelWidth); if (GUILayout.Button("Clear")) { foreach (NavMeshSurface s in targets) { ClearSurface(s); } SceneView.RepaintAll(); } if (GUILayout.Button("Bake")) { // Remove first to avoid double registration of the callback EditorApplication.update -= UpdateAsyncBuildOperations; EditorApplication.update += UpdateAsyncBuildOperations; foreach (NavMeshSurface surf in targets) { var oper = new AsyncBakeOperation(); oper.bakeData = InitializeBakeData(surf); oper.bakeOperation = surf.UpdateNavMesh(oper.bakeData); oper.surface = surf; s_BakeOperations.Add(oper); } } GUILayout.EndHorizontal(); } // Show progress for the selected targets for (int i = s_BakeOperations.Count - 1; i >= 0; --i) { if (!targets.Contains(s_BakeOperations[i].surface)) { continue; } var oper = s_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 = s_BakeOperations[i].bakeData; UnityEngine.AI.NavMeshBuilder.Cancel(bakeData); s_BakeOperations.RemoveAt(i); } EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), p, "Baking: " + (int)(100 * p) + "%"); if (p <= 1) { Repaint(); } GUILayout.EndHorizontal(); } }