using UnityEngine; using TMPro; using Unity.Netcode; namespace Northbound { /// /// 코어와 플레이어의 자원을 화면에 표시하는 통합 UI /// public class GameResourceUI : MonoBehaviour { [Header("Core Resource")] public TextMeshProUGUI coreResourceText; public TMP_FontAsset coreFontAsset; // 코어 텍스트용 폰트 [Header("Player Resource")] public TextMeshProUGUI playerResourceText; public TMP_FontAsset playerFontAsset; // 플레이어 텍스트용 폰트 public bool showPlayerResource = true; [Header("Display Settings")] public string corePrefix = "코어: "; public string playerPrefix = "보유: "; public string separator = " / "; [Header("Color Settings")] public bool useColorCoding = true; public Color normalColor = Color.white; public Color fullColor = Color.yellow; public Color emptyColor = Color.gray; [Header("Update Settings")] public float updateInterval = 0.1f; private float _lastUpdateTime; private int _cachedCoreResource = -1; private int _cachedPlayerResource = -1; private void Start() { // 폰트 애셋 적용 ApplyFontAssets(); } private void ApplyFontAssets() { if (coreResourceText != null && coreFontAsset != null) { coreResourceText.font = coreFontAsset; } if (playerResourceText != null && playerFontAsset != null) { playerResourceText.font = playerFontAsset; } } private void Update() { if (Time.time - _lastUpdateTime >= updateInterval) { UpdateUI(); _lastUpdateTime = Time.time; } } private void UpdateUI() { UpdateCoreResourceDisplay(); if (showPlayerResource) { UpdatePlayerResourceDisplay(); } } private void UpdateCoreResourceDisplay() { if (coreResourceText == null) return; if (CoreResourceManager.Instance == null || CoreResourceManager.Instance.mainCore == null) { coreResourceText.text = corePrefix + "---"; if (useColorCoding) coreResourceText.color = emptyColor; return; } int currentResources = CoreResourceManager.Instance.GetCurrentResources(); if (currentResources != _cachedCoreResource) { _cachedCoreResource = currentResources; var core = CoreResourceManager.Instance.mainCore; if (core.unlimitedStorage) { coreResourceText.text = $"{corePrefix}{currentResources}"; } else { coreResourceText.text = $"{corePrefix}{currentResources}{separator}{core.MaxStorageCapacity}"; // 색상 코딩 if (useColorCoding) { float fillPercentage = (float)currentResources / core.MaxStorageCapacity; if (fillPercentage >= 1.0f) coreResourceText.color = fullColor; else if (fillPercentage <= 0.1f) coreResourceText.color = emptyColor; else coreResourceText.color = normalColor; } } } } private void UpdatePlayerResourceDisplay() { if (playerResourceText == null) return; var localPlayer = GetLocalPlayer(); if (localPlayer == null) { playerResourceText.text = playerPrefix + "---"; if (useColorCoding) playerResourceText.color = emptyColor; return; } var inventory = localPlayer.GetComponent(); if (inventory == null) { playerResourceText.text = playerPrefix + "---"; if (useColorCoding) playerResourceText.color = emptyColor; return; } int currentAmount = inventory.CurrentResourceAmount; if (currentAmount != _cachedPlayerResource) { _cachedPlayerResource = currentAmount; playerResourceText.text = $"{playerPrefix}{currentAmount}{separator}{inventory.MaxResourceCapacity}"; // 색상 코딩 if (useColorCoding) { float fillPercentage = (float)currentAmount / inventory.MaxResourceCapacity; if (fillPercentage >= 1.0f) playerResourceText.color = fullColor; else if (fillPercentage <= 0.1f) playerResourceText.color = emptyColor; else playerResourceText.color = normalColor; } } } private GameObject GetLocalPlayer() { if (NetworkManager.Singleton == null || !NetworkManager.Singleton.IsClient) return null; ulong localClientId = NetworkManager.Singleton.LocalClientId; // PlayerObject가 있으면 사용 if (NetworkManager.Singleton.ConnectedClients.TryGetValue(localClientId, out var client)) { if (client.PlayerObject != null) { return client.PlayerObject.gameObject; } } // PlayerObject가 없으면 NetworkPlayerController로 찾기 // (서버 소유권으로 스폰한 경우 PlayerObject가 null일 수 있음) var allNetworkObjects = NetworkManager.Singleton.SpawnManager.SpawnedObjects; foreach (var kvp in allNetworkObjects) { var networkObj = kvp.Value; var playerController = networkObj.GetComponent(); if (playerController != null && playerController.IsLocalPlayer) { return networkObj.gameObject; } } return null; } private void OnEnable() { ApplyFontAssets(); UpdateUI(); } /// /// 런타임에서 폰트를 변경할 때 사용 /// public void SetCoreFontAsset(TMP_FontAsset fontAsset) { coreFontAsset = fontAsset; if (coreResourceText != null) { coreResourceText.font = fontAsset; } } /// /// 런타임에서 폰트를 변경할 때 사용 /// public void SetPlayerFontAsset(TMP_FontAsset fontAsset) { playerFontAsset = fontAsset; if (playerResourceText != null) { playerResourceText.font = fontAsset; } } } }