using System; using System.Collections.Generic; using Unity.VisualScripting; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using static UnityEngine.GraphicsBuffer; [ExecuteAlways] public class GameManager : MonoBehaviour { [HideInInspector] public static GameManager instance; [SerializeField] private Transform NodeParent; [SerializeField] private GameObject NodePrefab; [Header("Node Generation")] [Range(0, 20)] public float maxConnectionLength = 6; [Range(0, 1000)] public int nodeCount = 100; [Range(0, 100)] public float hoverRadius = 50; public List connections = new List(); private List nodes = new List(); public struct Connection { public Node nodeA, nodeB; public bool allowed; } public void GenerateAlongSphere() { connections.Clear(); nodes.Clear(); for (int i = NodeParent.childCount - 1; i >= 0; i--) DestroyImmediate(NodeParent.GetChild(i).gameObject); float radius = 20f; float goldenRatio = (1f + Mathf.Sqrt(5f)) / 2f; float angleIncrement = 2f * Mathf.PI * goldenRatio; for (int i = 0; i < nodeCount; i++) { float t = (float)i / nodeCount; // von 0 bis 1 float inclination = Mathf.Acos(1f - 2f * t); float azimuth = angleIncrement * i; float x = Mathf.Sin(inclination) * Mathf.Cos(azimuth); float y = Mathf.Sin(inclination) * Mathf.Sin(azimuth); float z = Mathf.Cos(inclination); Vector3 pos = new Vector3(x, y, z) * radius; var auto = Instantiate(NodePrefab, NodeParent); auto.transform.localPosition = pos; nodes.Add(auto.GetComponent()); } } public void GenerateConnections() { connections.Clear(); foreach (Node nodeA in nodes) { if (nodeA == null) continue; foreach (Node nodeB in nodes) { if (nodeB == null) continue; bool conExists = false; if (nodeA == nodeB || Math.Abs(Vector3.Distance(nodeA.transform.position, nodeB.transform.position)) > maxConnectionLength) continue; foreach (Connection con in connections) { if ((con.nodeA == nodeA && con.nodeB == nodeB) || (con.nodeA == nodeB && con.nodeB == nodeA)) { conExists = true; break; } } if (!conExists) connections.Add(new Connection { nodeA = nodeA, nodeB = nodeB }); } } } // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { } #if UNITY_EDITOR void OnDrawGizmos() { if (connections == null || SceneView.lastActiveSceneView?.camera == null) return; Camera cam = SceneView.lastActiveSceneView.camera; // Maus Screen-Koordinaten Vector2 guiPos = Event.current.mousePosition; guiPos.y = cam.pixelHeight - guiPos.y; Vector3 mousePos = new Vector3(guiPos.x, guiPos.y, 0); int closestIndex = -1; float closestDist = float.MaxValue; // Erster Durchlauf: kleinste Distanz merken for (int i = 0; i < connections.Count; i++) { var con = connections[i]; Vector3 a = cam.WorldToScreenPoint(con.nodeA.transform.position); Vector3 b = cam.WorldToScreenPoint(con.nodeB.transform.position); // Punkt-zu-Segment Abstand statt Dreiecksformel Vector3 ab = b - a; Vector3 am = mousePos - a; float t = Mathf.Clamp01(Vector3.Dot(am, ab) / ab.sqrMagnitude); Vector3 proj = a + t * ab; float dist = Vector3.Distance(mousePos, proj); if (dist < closestDist) { closestDist = dist; closestIndex = i; } } // Zweiter Durchlauf: zeichnen for (int i = 0; i < connections.Count; i++) { var con = connections[i]; Handles.color = con.allowed ? Color.green : Color.red; float thickness = (i == closestIndex && closestDist < hoverRadius) ? 5f : 1f; Handles.DrawLine(con.nodeA.transform.position, con.nodeB.transform.position, thickness); } } #endif } #if UNITY_EDITOR [CustomEditor(typeof(GameManager))] public class GameManagerEditor : Editor { public override void OnInspectorGUI() { // Standard-Inspector zeichnen DrawDefaultInspector(); GameManager gm = (GameManager)target; GUILayout.BeginHorizontal(); if (GUILayout.Button("Generate Sphere")) { gm.GenerateAlongSphere(); } if (GUILayout.Button("Generate Connections")) { gm.GenerateConnections(); } GUILayout.EndHorizontal(); if (GUILayout.Button("Generate")) { gm.GenerateAlongSphere(); gm.GenerateConnections(); } } } [InitializeOnLoad] public static class SceneViewUpdater { static SceneViewUpdater() { EditorApplication.update += () => { if (SceneView.lastActiveSceneView != null) SceneView.lastActiveSceneView.Repaint(); }; } } #endif