Files
Northbound/Assets/Scripts/GameResourceUI.cs
dal4segno 4ffbbb0aff 모든 네트워크 오브젝트의 소유권을 서버가 갖도록 함
Distributable -> None
관련 사이드 이펙트로 인한 버그 수정
2026-02-18 02:18:42 +09:00

229 lines
7.4 KiB
C#

using UnityEngine;
using TMPro;
using Unity.Netcode;
namespace Northbound
{
/// <summary>
/// 코어와 플레이어의 자원을 화면에 표시하는 통합 UI
/// </summary>
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<PlayerResourceInventory>();
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<NetworkPlayerController>();
if (playerController != null && playerController.IsLocalPlayer)
{
return networkObj.gameObject;
}
}
return null;
}
private void OnEnable()
{
ApplyFontAssets();
UpdateUI();
}
/// <summary>
/// 런타임에서 폰트를 변경할 때 사용
/// </summary>
public void SetCoreFontAsset(TMP_FontAsset fontAsset)
{
coreFontAsset = fontAsset;
if (coreResourceText != null)
{
coreResourceText.font = fontAsset;
}
}
/// <summary>
/// 런타임에서 폰트를 변경할 때 사용
/// </summary>
public void SetPlayerFontAsset(TMP_FontAsset fontAsset)
{
playerFontAsset = fontAsset;
if (playerResourceText != null)
{
playerResourceText.font = fontAsset;
}
}
}
}