NavigationSampleProjectSettingsGenerator.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEngine.AI;
  4. namespace Unity.AI.Navigation.Samples.Editor
  5. {
  6. /// <summary>
  7. /// This class creates (if missing) or resets (after reimporting the samples) the agent types used by the samples.
  8. /// It is in no way necessary for using the Navigation package and is only used for the correct functioning of the samples.
  9. /// </summary>
  10. public static class NavigationSampleProjectSettingsGenerator
  11. {
  12. const string k_NavMeshSettingsPath = "ProjectSettings/NavMeshAreas.asset";
  13. const float k_DefaultAgentRadius = 0.5f;
  14. const float k_DefaultAgentHeight = 2.0f;
  15. const float k_DefaultAgentClimb = 0.4f;
  16. const float k_DefaultAgentSlope = 45.0f;
  17. const string k_HumanoidAgentTypeName = "Humanoid for Navigation Sample";
  18. const int k_HumanoidAgentTypeID = 1;
  19. const float k_HumanoidAgentClimb = 0.75f;
  20. const string k_OgreAgentTypeName = "Ogre for Navigation Sample";
  21. const int k_OgreAgentTypeID = 2;
  22. const float k_OgreAgentRadius = 1.0f;
  23. const float k_OgreAgentSlope = 36.0f;
  24. static SerializedObject s_NavMeshParameters;
  25. static SerializedProperty s_AgentsSettings;
  26. static SerializedProperty s_SettingNames;
  27. public static void GenerateAllProjectSettings(NavigationSampleSettingsState settingsState)
  28. {
  29. s_NavMeshParameters = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(k_NavMeshSettingsPath)[0]);
  30. s_AgentsSettings = s_NavMeshParameters.FindProperty("m_Settings");
  31. s_SettingNames = s_NavMeshParameters.FindProperty("m_SettingNames");
  32. var hasInitializedOnProjectLoad = settingsState.generated;
  33. GenerateProjectSettings(k_HumanoidAgentTypeName, k_HumanoidAgentTypeID, CreateHumanoidAgentSettings, hasInitializedOnProjectLoad);
  34. GenerateProjectSettings(k_OgreAgentTypeName, k_OgreAgentTypeID, CreateOgreAgentSettings, hasInitializedOnProjectLoad);
  35. s_NavMeshParameters.ApplyModifiedProperties();
  36. settingsState.generated = true;
  37. AssetDatabase.Refresh();
  38. }
  39. static void GenerateProjectSettings(string agentTypeName, int agentTypeID, CreateAgentSettings createAgentSettings, bool hasInitializedOnProjectLoad)
  40. {
  41. var agentProperty = GetSerializedSettingsByID(agentTypeID, out var index);
  42. if (index < 0)
  43. {
  44. // Create new settings
  45. var agentSettings = createAgentSettings();
  46. agentSettings.agentTypeID = agentTypeID;
  47. AddAgentSettings(agentSettings, agentTypeName, agentTypeID);
  48. }
  49. else
  50. {
  51. if (!HasSettingsNameAtIndex(index, agentTypeName))
  52. {
  53. // Don't update the settings
  54. var settingsName = s_SettingNames.GetArrayElementAtIndex(index).stringValue;
  55. if (!IsAgentTypeSetWithDefaultValues(index, agentTypeID))
  56. {
  57. Debug.LogWarning($"The agent type {agentTypeName} used in the Navigation Samples could not be created. The agent type {settingsName} will be used instead. {settingsName} does not have the expected values for {agentTypeName}. The expected values for {agentTypeName} are written in the README.md file of the samples. The values of agent types are updatable in the Agents tab of the AI > Navigation window.");
  58. }
  59. }
  60. else if (!hasInitializedOnProjectLoad && !IsAgentTypeSetWithDefaultValues(index, agentTypeID))
  61. {
  62. // Update existing settings to default values
  63. var radius = agentProperty.FindPropertyRelative("agentRadius").floatValue;
  64. var height = agentProperty.FindPropertyRelative("agentHeight").floatValue;
  65. var climb = agentProperty.FindPropertyRelative("agentClimb").floatValue;
  66. var slope = agentProperty.FindPropertyRelative("agentSlope").floatValue;
  67. var tempAgentSettings = createAgentSettings();
  68. UpdateSettings(agentProperty, tempAgentSettings);
  69. NavMesh.RemoveSettings(tempAgentSettings.agentTypeID);
  70. Debug.Log($"Navigation Samples reimport detected. The agent type {agentTypeName} has been reset to its default values. Its values before the reset were: Radius = {radius}, Height = {height}, Step height = {climb} and Max Slope = {slope}.");
  71. }
  72. }
  73. }
  74. static bool IsAgentTypeSetWithDefaultValues(int index, int agentTypeID)
  75. {
  76. var agentTypeSettings = s_AgentsSettings.GetArrayElementAtIndex(index);
  77. var radius = agentTypeSettings.FindPropertyRelative("agentRadius").floatValue;
  78. var height = agentTypeSettings.FindPropertyRelative("agentHeight").floatValue;
  79. var climb = agentTypeSettings.FindPropertyRelative("agentClimb").floatValue;
  80. var slope = agentTypeSettings.FindPropertyRelative("agentSlope").floatValue;
  81. var result = false;
  82. switch (agentTypeID)
  83. {
  84. case k_HumanoidAgentTypeID:
  85. result = radius == k_DefaultAgentRadius && height == k_DefaultAgentHeight && climb == k_HumanoidAgentClimb && slope == k_DefaultAgentSlope;
  86. break;
  87. case k_OgreAgentTypeID:
  88. result = radius == k_OgreAgentRadius && height == k_DefaultAgentHeight && climb == k_DefaultAgentClimb && slope == k_OgreAgentSlope;
  89. break;
  90. }
  91. return result;
  92. }
  93. delegate NavMeshBuildSettings CreateAgentSettings();
  94. static NavMeshBuildSettings CreateHumanoidAgentSettings()
  95. {
  96. var humanoidAgentSettings = NavMesh.CreateSettings();
  97. humanoidAgentSettings.agentRadius = k_DefaultAgentRadius;
  98. humanoidAgentSettings.agentHeight = k_DefaultAgentHeight;
  99. humanoidAgentSettings.agentClimb = k_HumanoidAgentClimb;
  100. humanoidAgentSettings.agentSlope = k_DefaultAgentSlope;
  101. return humanoidAgentSettings;
  102. }
  103. static NavMeshBuildSettings CreateOgreAgentSettings()
  104. {
  105. var ogreAgentSettings = NavMesh.CreateSettings();
  106. ogreAgentSettings.agentRadius = k_OgreAgentRadius;
  107. ogreAgentSettings.agentHeight = k_DefaultAgentHeight;
  108. ogreAgentSettings.agentClimb = k_DefaultAgentClimb;
  109. ogreAgentSettings.agentSlope = k_OgreAgentSlope;
  110. return ogreAgentSettings;
  111. }
  112. static SerializedProperty GetSerializedSettingsByID(int agentTypeID, out int index)
  113. {
  114. index = -1;
  115. SerializedProperty settings = null;
  116. for (var i = 0; i < s_AgentsSettings.arraySize; i++)
  117. {
  118. if (s_AgentsSettings.GetArrayElementAtIndex(i).FindPropertyRelative("agentTypeID").intValue == agentTypeID)
  119. {
  120. index = i;
  121. settings = s_AgentsSettings.GetArrayElementAtIndex(i);
  122. break;
  123. }
  124. }
  125. return settings;
  126. }
  127. static bool HasSettingsNameAtIndex(int index, string agentTypeName)
  128. {
  129. return s_SettingNames.GetArrayElementAtIndex(index).stringValue.Equals(agentTypeName);
  130. }
  131. static void AddAgentSettings(NavMeshBuildSettings agentSettings, string agentTypeName, int agentTypeID)
  132. {
  133. var nbNames = s_SettingNames.arraySize;
  134. s_SettingNames.InsertArrayElementAtIndex(nbNames);
  135. var newName = s_SettingNames.GetArrayElementAtIndex(nbNames);
  136. newName.stringValue = agentTypeName;
  137. var nbAgents = s_AgentsSettings.arraySize;
  138. s_AgentsSettings.InsertArrayElementAtIndex(nbAgents);
  139. var addedAgentType = s_AgentsSettings.GetArrayElementAtIndex(nbAgents);
  140. UpdateSettings(addedAgentType, agentSettings);
  141. SetAgentPropertyValue(addedAgentType, "agentTypeID", agentTypeID);
  142. }
  143. static void UpdateSettings(SerializedProperty agentToUpdate, NavMeshBuildSettings newSettings)
  144. {
  145. SetAgentPropertyValue(agentToUpdate, "agentRadius", newSettings.agentRadius);
  146. SetAgentPropertyValue(agentToUpdate, "agentHeight", newSettings.agentHeight);
  147. SetAgentPropertyValue(agentToUpdate, "agentClimb", newSettings.agentClimb);
  148. SetAgentPropertyValue(agentToUpdate, "agentSlope", newSettings.agentSlope);
  149. }
  150. static void SetAgentPropertyValue(SerializedProperty agent, string propertyName, int value)
  151. {
  152. var property = agent.FindPropertyRelative(propertyName);
  153. property.intValue = value;
  154. }
  155. static void SetAgentPropertyValue(SerializedProperty agent, string propertyName, float value)
  156. {
  157. var property = agent.FindPropertyRelative(propertyName);
  158. property.floatValue = value;
  159. }
  160. }
  161. }