using UnityEngine; using UnityEditor; using UnityEngine.AI; public class SpawnEdgeMarkerTool2D : EditorWindow { public Transform IslandCenter; public GameObject MarkerPrefab; public float SearchRadius = 10f; public int RayCount = 16; public float StepSize = 0.25f; public float RayDepth = 2f; public bool ShowSceneGizmos = true; [MenuItem("Tools/2D Spawn Edge Marker Tool")] public static void ShowWindow() => GetWindow("2D Spawn Edge Tool"); private void OnEnable() => SceneView.duringSceneGui += OnSceneGUI; private void OnDisable() => SceneView.duringSceneGui -= OnSceneGUI; private void OnGUI() { IslandCenter = (Transform)EditorGUILayout.ObjectField("Island Center", IslandCenter, typeof(Transform), true); MarkerPrefab = (GameObject)EditorGUILayout.ObjectField("Spawn Marker Prefab", MarkerPrefab, typeof(GameObject), false); EditorGUILayout.Space(); SearchRadius = EditorGUILayout.FloatField("Start Radius", SearchRadius); RayCount = EditorGUILayout.IntField("Ray Count", RayCount); StepSize = EditorGUILayout.FloatField("Step Size", StepSize); RayDepth = EditorGUILayout.FloatField("NavMesh Sample Depth", RayDepth); ShowSceneGizmos = EditorGUILayout.Toggle("Visualize in Scene", ShowSceneGizmos); EditorGUILayout.Space(); if (GUILayout.Button("Place Spawn Markers")) { if (IslandCenter == null) { Debug.LogError("Island Center must be assigned!"); return; } PlaceSpawnMarkers2D(); } } private void OnSceneGUI(SceneView sceneView) { if (!ShowSceneGizmos || IslandCenter == null) return; Vector3 center = IslandCenter.position; Handles.color = Color.cyan; for (int i = 0; i < RayCount; i++) { float angle = (360f / RayCount) * i; Vector3 direction = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad), 0f); Vector3 start = center + direction * SearchRadius; Handles.SphereHandleCap(0, start, Quaternion.identity, 0.2f, EventType.Repaint); Handles.DrawLine(start, start - direction * 1.5f, 2); } SceneView.RepaintAll(); } private void PlaceSpawnMarkers2D() { Vector3 center = IslandCenter.position; GameObject parent = new GameObject("EdgeSpawnMarkers2D"); Undo.RegisterCreatedObjectUndo(parent, "Create Spawn Markers"); for (int i = 0; i < RayCount; i++) { float angle = (360f / RayCount) * i; Vector3 direction = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad), 0f); Vector3 start = center + direction * SearchRadius; for (float d = 0; d < SearchRadius; d += StepSize) { Vector3 probe = start - direction * d; // You can change this check based on your environment: if (NavMesh.SamplePosition(probe, out NavMeshHit hit, RayDepth, NavMesh.AllAreas)) { GameObject spawnPoint = MarkerPrefab != null ? (GameObject)PrefabUtility.InstantiatePrefab(MarkerPrefab) : new GameObject($"SpawnPoint_{i}"); spawnPoint.transform.position = hit.position; spawnPoint.transform.SetParent(parent.transform); Undo.RegisterCreatedObjectUndo(spawnPoint, "Place SpawnPoint"); break; } // Optional: For purely 2D check using layer // if (Physics2D.OverlapPoint(probe)) { ... } } } Debug.Log($"? Placed {RayCount} 2D spawn markers."); } }