using UnityEngine; using TMPro; public class SelectionManager : MonoBehaviour { public static SelectionManager Instance { get; private set; } [Header("Nameplate")] public Canvas worldSpaceCanvas; // a World Space Canvas in scene public GameObject nameplatePrefab; // prefab containing TextMeshProUGUI public Vector3 nameplateOffset = new Vector3(0, 2.2f, 0); [Header("Colors")] public Color friendlyColor = Color.green; public Color neutralColor = Color.cyan; public Color enemyColor = Color.red; Selectable current; GameObject activeNameplate; NameplateController nameplateController; void Awake() { if (Instance != null && Instance != this) { Debug.LogWarning("Multiple SelectionManager instances detected. Destroying duplicate.", gameObject); Destroy(gameObject); return; } Instance = this; } void OnDestroy() { if (Instance == this) Instance = null; } public void Select(Selectable s) { if (s == null) { ClearSelection(); return; } if (current == s) return; ClearSelection(); current = s; current.OnSelected(); CreateNameplate(s.displayName, GetColorForAttitude(s.attitude)); } public void Select(Building b) { if (b == null) { ClearSelection(); return; } ClearSelection(); b.OnSelected(); CreateNameplate(b.displayName, GetColorForAttitude(b.attitude)); } void CreateNameplate(string displayName, Color color) { if (nameplatePrefab == null || worldSpaceCanvas == null) return; activeNameplate = Instantiate(nameplatePrefab, worldSpaceCanvas.transform, false); nameplateController = activeNameplate.GetComponent(); if (nameplateController == null) { Debug.LogError("NameplateController not found on nameplate prefab!", nameplatePrefab); DestroyNameplate(); return; } if (current != null) { nameplateController.Initialize(current, color, nameplateOffset); } else { // For buildings, we'll update in LateUpdate with the last known target nameplateController.SetDisplayName(displayName); nameplateController.ApplyColor(color); } } public void ClearSelection() { if (current != null) { current.OnDeselected(); current = null; } DestroyNameplate(); } void DestroyNameplate() { if (activeNameplate != null) Destroy(activeNameplate); activeNameplate = null; nameplateController = null; } Color GetColorForAttitude(Attitude a) { return a switch { Attitude.Friendly => friendlyColor, Attitude.Neutral => neutralColor, Attitude.Enemy => enemyColor, _ => neutralColor }; } void LateUpdate() { // Update nameplate position if it exists and has a target if (nameplateController != null && current != null) { nameplateController.FollowTarget(current.transform, nameplateOffset); } // Clean up orphaned nameplates if current object was destroyed if (current == null && activeNameplate != null) { DestroyNameplate(); } } }