AIBaseEditor.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using UnityEditor;
  2. using UnityEngine;
  3. namespace Pathfinding {
  4. [CustomEditor(typeof(AIBase), true)]
  5. [CanEditMultipleObjects]
  6. public class BaseAIEditor : EditorBase {
  7. float lastSeenCustomGravity = float.NegativeInfinity;
  8. protected override void Inspector () {
  9. var isAIPath = typeof(AIPath).IsAssignableFrom(target.GetType());
  10. Section("Shape");
  11. FloatField("radius", min: 0.01f);
  12. FloatField("height", min: 0.01f);
  13. Section("Pathfinding");
  14. if (PropertyField("canSearch")) {
  15. EditorGUI.indentLevel++;
  16. FloatField("repathRate", min: 0f);
  17. EditorGUI.indentLevel--;
  18. }
  19. Section("Movement");
  20. PropertyField("canMove");
  21. FloatField("maxSpeed", min: 0f);
  22. if (isAIPath) {
  23. EditorGUI.BeginChangeCheck();
  24. var acceleration = FindProperty("maxAcceleration");
  25. int acc = acceleration.hasMultipleDifferentValues ? -1 : (acceleration.floatValue >= 0 ? 1 : 0);
  26. var nacc = EditorGUILayout.Popup("Max Acceleration", acc, new [] { "Default", "Custom" });
  27. if (EditorGUI.EndChangeCheck()) {
  28. if (nacc == 0) acceleration.floatValue = -2.5f;
  29. else if (acceleration.floatValue < 0) acceleration.floatValue = 10;
  30. }
  31. if (!acceleration.hasMultipleDifferentValues && nacc == 1) {
  32. EditorGUI.indentLevel++;
  33. PropertyField(acceleration.propertyPath);
  34. EditorGUI.indentLevel--;
  35. acceleration.floatValue = Mathf.Max(acceleration.floatValue, 0.01f);
  36. }
  37. Popup("orientation", new [] { new GUIContent("ZAxisForward (for 3D games)"), new GUIContent("YAxisForward (for 2D games)") });
  38. } else {
  39. FloatField("acceleration", min: 0f);
  40. // The RichAI script doesn't really support any orientation other than Z axis forward, so don't expose it in the inspector
  41. FindProperty("orientation").enumValueIndex = (int)OrientationMode.ZAxisForward;
  42. }
  43. if (PropertyField("enableRotation")) {
  44. EditorGUI.indentLevel++;
  45. FloatField("rotationSpeed", min: 0f);
  46. PropertyField("slowWhenNotFacingTarget");
  47. EditorGUI.indentLevel--;
  48. }
  49. if (isAIPath) {
  50. FloatField("pickNextWaypointDist", min: 0f);
  51. FloatField("slowdownDistance", min: 0f);
  52. } else {
  53. FloatField("slowdownTime", min: 0f);
  54. FloatField("wallForce", min: 0f);
  55. FloatField("wallDist", min: 0f);
  56. PropertyField("funnelSimplification");
  57. }
  58. FloatField("endReachedDistance", min: 0f);
  59. if (isAIPath) {
  60. PropertyField("alwaysDrawGizmos");
  61. PropertyField("whenCloseToDestination");
  62. PropertyField("constrainInsideGraph");
  63. }
  64. var mono = target as MonoBehaviour;
  65. var rigid = mono.GetComponent<Rigidbody>();
  66. var rigid2D = mono.GetComponent<Rigidbody2D>();
  67. var controller = mono.GetComponent<CharacterController>();
  68. var canUseGravity = (controller != null && controller.enabled) || ((rigid == null || rigid.isKinematic) && (rigid2D == null || rigid2D.isKinematic));
  69. var gravity = FindProperty("gravity");
  70. var groundMask = FindProperty("groundMask");
  71. if (canUseGravity) {
  72. EditorGUI.BeginChangeCheck();
  73. int grav = gravity.hasMultipleDifferentValues ? -1 : (gravity.vector3Value == Vector3.zero ? 0 : (float.IsNaN(gravity.vector3Value.x) ? 1 : 2));
  74. var ngrav = EditorGUILayout.Popup("Gravity", grav, new [] { "None", "Use Project Settings", "Custom" });
  75. if (EditorGUI.EndChangeCheck()) {
  76. if (ngrav == 0) gravity.vector3Value = Vector3.zero;
  77. else if (ngrav == 1) gravity.vector3Value = new Vector3(float.NaN, float.NaN, float.NaN);
  78. else if (float.IsNaN(gravity.vector3Value.x) || gravity.vector3Value == Vector3.zero) gravity.vector3Value = Physics.gravity;
  79. lastSeenCustomGravity = float.NegativeInfinity;
  80. }
  81. if (!gravity.hasMultipleDifferentValues) {
  82. // A sort of delayed Vector3 field (to prevent the field from dissappearing if you happen to enter zeroes into x, y and z for a short time)
  83. // Note: cannot use != in this case because that will not give the correct result in case of NaNs
  84. if (!(gravity.vector3Value == Vector3.zero)) lastSeenCustomGravity = Time.realtimeSinceStartup;
  85. if (Time.realtimeSinceStartup - lastSeenCustomGravity < 2f) {
  86. EditorGUI.indentLevel++;
  87. if (!float.IsNaN(gravity.vector3Value.x)) {
  88. PropertyField(gravity.propertyPath);
  89. }
  90. if (controller == null || !controller.enabled) {
  91. PropertyField(groundMask.propertyPath, "Raycast Ground Mask");
  92. }
  93. EditorGUI.indentLevel--;
  94. }
  95. }
  96. } else {
  97. EditorGUI.BeginDisabledGroup(true);
  98. EditorGUILayout.Popup(new GUIContent(gravity.displayName, "Disabled because a non-kinematic rigidbody is attached"), 0, new [] { new GUIContent("Handled by Rigidbody") });
  99. EditorGUI.EndDisabledGroup();
  100. }
  101. if ((rigid != null || rigid2D != null) && (controller != null && controller.enabled)) {
  102. EditorGUILayout.HelpBox("You are using both a Rigidbody and a Character Controller. Those components are not really designed for that. Please use only one of them.", MessageType.Warning);
  103. }
  104. }
  105. }
  106. }