[UI] 이상 상태 슬롯 UI 개선
- 지속 시간 표시가 주기적으로 업데이트되도록 수정 - fill 이미지가 시간이 지날수록 채워지도록 변경 - 남은 시간 정수로만 표시 - 비활성화된 Cooltime 요소 자동 활성화 - Animator Controller 제거로 UI 정상 표시 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,6 @@ GameObject:
|
||||
- component: {fileID: 8742265258977334277}
|
||||
- component: {fileID: 3698892055439276710}
|
||||
- component: {fileID: 9068576939756357679}
|
||||
- component: {fileID: 8350059981962847808}
|
||||
- component: {fileID: 800351318774919540}
|
||||
- component: {fileID: 5402880947663824673}
|
||||
m_Layer: 5
|
||||
@@ -80,50 +79,6 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8350059981962847808
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3383354828365798028}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 3
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 9068576939756357679}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!95 &800351318774919540
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
@@ -134,7 +89,7 @@ Animator:
|
||||
m_GameObject: {fileID: 3383354828365798028}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: f6c1759d41da8c942acb67824989a5b8, type: 2}
|
||||
m_Controller: {fileID: 0}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
@@ -489,7 +444,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_FillAmount
|
||||
value: 0
|
||||
value: 0.46
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_FillMethod
|
||||
@@ -501,7 +456,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_FillClockwise
|
||||
value: 1
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_text
|
||||
@@ -535,6 +490,10 @@ PrefabInstance:
|
||||
propertyPath: 'm_ActiveFontFeatures.Array.data[0]'
|
||||
value: 1801810542
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1819597544659277106, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_Controller
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0.5
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Colosseum.UI
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Debug.Log("[AbnormalityListUI] Start() called");
|
||||
|
||||
if (autoFindPlayer)
|
||||
{
|
||||
// 로컬 플레이어 찾기
|
||||
@@ -50,6 +52,10 @@ namespace Colosseum.UI
|
||||
|
||||
// 슬롯 풀 초기화
|
||||
InitializeSlotPool();
|
||||
|
||||
Debug.Log($"[AbnormalityListUI] slotPrefab: {(slotPrefab != null ? slotPrefab.name : "NULL")}");
|
||||
Debug.Log($"[AbnormalityListUI] buffContainer: {(buffContainer != null ? buffContainer.name : "NULL")}");
|
||||
Debug.Log($"[AbnormalityListUI] debuffContainer: {(debuffContainer != null ? debuffContainer.name : "NULL")}");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -65,6 +71,12 @@ namespace Colosseum.UI
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 타겟이 없으면 주기적으로 플레이어 찾기
|
||||
if (targetManager == null && autoFindPlayer && Time.frameCount % 30 == 0)
|
||||
{
|
||||
FindLocalPlayer();
|
||||
}
|
||||
|
||||
// 주기적으로 UI 갱신 (성능 최적화를 위해 매 프레임이 아닌 일정 간격으로)
|
||||
if (Time.frameCount % 10 == 0) // 10프레임마다 한 번
|
||||
{
|
||||
@@ -78,14 +90,20 @@ namespace Colosseum.UI
|
||||
private void FindLocalPlayer()
|
||||
{
|
||||
var playerObjects = FindObjectsByType<AbnormalityManager>(FindObjectsSortMode.None);
|
||||
Debug.Log($"[AbnormalityListUI] Found {playerObjects.Length} AbnormalityManager(s)");
|
||||
|
||||
foreach (var manager in playerObjects)
|
||||
{
|
||||
// 네트워크 오브젝트인 경우 로컬 플레이어 확인
|
||||
if (manager.TryGetComponent<Unity.Netcode.NetworkObject>(out var netObj) && netObj.IsOwner)
|
||||
if (manager.TryGetComponent<Unity.Netcode.NetworkObject>(out var netObj))
|
||||
{
|
||||
SetTarget(manager);
|
||||
return;
|
||||
Debug.Log($"[AbnormalityListUI] Checking {manager.gameObject.name}, IsOwner: {netObj.IsOwner}");
|
||||
if (netObj.IsOwner)
|
||||
{
|
||||
Debug.Log($"[AbnormalityListUI] Setting target to local player: {manager.gameObject.name}");
|
||||
SetTarget(manager);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,8 +111,13 @@ namespace Colosseum.UI
|
||||
// 첫 번째 플레이어 사용 (싱글플레이어용)
|
||||
if (playerObjects.Length > 0)
|
||||
{
|
||||
Debug.Log($"[AbnormalityListUI] No local player found, using first manager: {playerObjects[0].gameObject.name}");
|
||||
SetTarget(playerObjects[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[AbnormalityListUI] No AbnormalityManager found!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,6 +126,8 @@ namespace Colosseum.UI
|
||||
/// <param name="manager">추적할 AbnormalityManager</param>
|
||||
public void SetTarget(AbnormalityManager manager)
|
||||
{
|
||||
Debug.Log($"[AbnormalityListUI] SetTarget called with: {(manager != null ? manager.gameObject.name : "null")}");
|
||||
|
||||
// 기존 구독 해제
|
||||
if (targetManager != null)
|
||||
{
|
||||
@@ -119,6 +144,7 @@ namespace Colosseum.UI
|
||||
targetManager.OnAbnormalityAdded += OnAbnormalityAdded;
|
||||
targetManager.OnAbnormalityRemoved += OnAbnormalityRemoved;
|
||||
targetManager.OnAbnormalitiesChanged += OnAbnormalitiesChanged;
|
||||
Debug.Log("[AbnormalityListUI] Events subscribed successfully");
|
||||
}
|
||||
|
||||
// 즉시 UI 갱신
|
||||
@@ -193,6 +219,7 @@ namespace Colosseum.UI
|
||||
/// </summary>
|
||||
private void OnAbnormalityAdded(ActiveAbnormality abnormality)
|
||||
{
|
||||
Debug.Log($"[AbnormalityListUI] OnAbnormalityAdded event received: {abnormality.Data.abnormalityName}");
|
||||
ForceRefreshUI();
|
||||
}
|
||||
|
||||
@@ -201,6 +228,7 @@ namespace Colosseum.UI
|
||||
/// </summary>
|
||||
private void OnAbnormalityRemoved(ActiveAbnormality abnormality)
|
||||
{
|
||||
Debug.Log($"[AbnormalityListUI] OnAbnormalityRemoved event received: {abnormality.Data.abnormalityName}");
|
||||
ForceRefreshUI();
|
||||
}
|
||||
|
||||
@@ -209,6 +237,7 @@ namespace Colosseum.UI
|
||||
/// </summary>
|
||||
private void OnAbnormalitiesChanged()
|
||||
{
|
||||
Debug.Log("[AbnormalityListUI] OnAbnormalitiesChanged event received");
|
||||
ForceRefreshUI();
|
||||
}
|
||||
|
||||
@@ -217,7 +246,11 @@ namespace Colosseum.UI
|
||||
/// </summary>
|
||||
public void ForceRefreshUI()
|
||||
{
|
||||
if (targetManager == null) return;
|
||||
if (targetManager == null)
|
||||
{
|
||||
Debug.LogWarning("[AbnormalityListUI] ForceRefreshUI called but targetManager is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// 모든 슬롯 반환
|
||||
foreach (var slot in activeSlots.ToArray())
|
||||
@@ -229,15 +262,23 @@ namespace Colosseum.UI
|
||||
|
||||
// 활성화된 이상 상태 표시
|
||||
var abnormalities = targetManager.ActiveAbnormalities;
|
||||
Debug.Log($"[AbnormalityListUI] ForceRefreshUI: {abnormalities.Count} abnormalities found");
|
||||
|
||||
foreach (var abnormality in abnormalities)
|
||||
{
|
||||
var slot = GetSlot();
|
||||
if (slot == null) continue;
|
||||
if (slot == null)
|
||||
{
|
||||
Debug.LogWarning("[AbnormalityListUI] Could not get slot from pool");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 버프/디버프에 따라 적절한 컨테이너에 배치
|
||||
Transform container = abnormality.Data.isDebuff ? debuffContainer : buffContainer;
|
||||
if (container == null) container = transform;
|
||||
|
||||
Debug.Log($"[AbnormalityListUI] Adding slot for: {abnormality.Data.abnormalityName}, isDebuff: {abnormality.Data.isDebuff}, container: {container.name}");
|
||||
|
||||
slot.transform.SetParent(container, false);
|
||||
slot.Initialize(abnormality);
|
||||
slot.gameObject.SetActive(true);
|
||||
@@ -261,6 +302,24 @@ namespace Colosseum.UI
|
||||
{
|
||||
ForceRefreshUI();
|
||||
}
|
||||
|
||||
// 활성 슬롯들의 지속 시간 업데이트
|
||||
UpdateSlotDurations();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 활성 슬롯의 지속 시간 업데이트
|
||||
/// </summary>
|
||||
private void UpdateSlotDurations()
|
||||
{
|
||||
foreach (var slot in activeSlots)
|
||||
{
|
||||
if (slot != null && slot.TrackedAbnormality != null)
|
||||
{
|
||||
var abnormality = slot.TrackedAbnormality;
|
||||
slot.UpdateDisplay(abnormality.RemainingDuration, abnormality.Data.duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -55,6 +55,12 @@ namespace Colosseum.UI
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[AbnormalitySlotUI] Initialize: {abnormality.Data.abnormalityName}, icon: {abnormality.Data.icon?.name ?? "null"}");
|
||||
Debug.Log($"[AbnormalitySlotUI] UI References - iconImage: {(iconImage != null ? "OK" : "NULL")}, durationFill: {(durationFill != null ? "OK" : "NULL")}, durationText: {(durationText != null ? "OK" : "NULL")}, backgroundImage: {(backgroundImage != null ? "OK" : "NULL")}");
|
||||
|
||||
// Cooltime 요소 활성화 (부모 게임오브젝트들이 비활성화되어 있을 수 있음)
|
||||
EnableDurationElements();
|
||||
|
||||
// 아이콘 설정
|
||||
if (iconImage != null)
|
||||
{
|
||||
@@ -68,6 +74,11 @@ namespace Colosseum.UI
|
||||
effectNameText.text = abnormality.Data.abnormalityName;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[AbnormalitySlotUI] effectNameText is null");
|
||||
}
|
||||
|
||||
// 배경 색상 설정 (버프/디버프 구분)
|
||||
if (backgroundImage != null)
|
||||
{
|
||||
@@ -79,104 +90,63 @@ namespace Colosseum.UI
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 화면 표시 업데이트
|
||||
/// UI 표시 업데이트
|
||||
/// </summary>
|
||||
/// <param name="remainingDuration">남은 시간</param>
|
||||
/// <param name="totalDuration">전체 시간</param>
|
||||
/// <param name="remainingDuration">남은 지속 시간</param>
|
||||
/// <param name="totalDuration">전체 지속 시간</param>
|
||||
public void UpdateDisplay(float remainingDuration, float totalDuration)
|
||||
{
|
||||
// 지속 시간 채우기 업데이트
|
||||
if (durationFill != null)
|
||||
// 지속 시간 채우기 이미지 업데이트 (시간이 지날수록 채워짐)
|
||||
if (durationFill != null && totalDuration > 0)
|
||||
{
|
||||
if (totalDuration > 0f)
|
||||
{
|
||||
float fillAmount = Mathf.Clamp01(remainingDuration / totalDuration);
|
||||
durationFill.fillAmount = fillAmount;
|
||||
durationFill.enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 영구 효과
|
||||
durationFill.fillAmount = 1f;
|
||||
}
|
||||
durationFill.fillAmount = 1f - (remainingDuration / totalDuration);
|
||||
}
|
||||
|
||||
// 남은 시간 텍스트 업데이트
|
||||
// 남은 시간 텍스트 업데이트 (정수만 표시)
|
||||
if (durationText != null)
|
||||
{
|
||||
if (totalDuration > 0f)
|
||||
if (remainingDuration > 60f)
|
||||
{
|
||||
if (remainingDuration >= 60f)
|
||||
{
|
||||
durationText.text = $"{remainingDuration / 60f:F0}m";
|
||||
}
|
||||
else if (remainingDuration >= 1f)
|
||||
{
|
||||
durationText.text = $"{remainingDuration:F0}s";
|
||||
}
|
||||
else
|
||||
{
|
||||
durationText.text = $"{remainingDuration:F1}s";
|
||||
}
|
||||
durationText.text = $"{(int)(remainingDuration / 60f)}:{(int)(remainingDuration % 60f):D2}";
|
||||
}
|
||||
else if (remainingDuration > 0f)
|
||||
{
|
||||
durationText.text = $"{Mathf.CeilToInt(remainingDuration)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 영구 효과
|
||||
durationText.text = "∞";
|
||||
durationText.text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 프레임마다 호출하여 추적 중인 효과 업데이트
|
||||
/// 지속 시간 관련 UI 요소들의 부모 게임오브젝트를 활성화합니다.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
private void EnableDurationElements()
|
||||
{
|
||||
if (trackedAbnormality == null)
|
||||
// durationFill의 모든 부모 게임오브젝트 활성화
|
||||
if (durationFill != null)
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
return;
|
||||
Transform parent = durationFill.transform.parent;
|
||||
while (parent != null && parent != transform)
|
||||
{
|
||||
parent.gameObject.SetActive(true);
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateDisplay(trackedAbnormality.RemainingDuration, trackedAbnormality.Data.duration);
|
||||
// durationText의 모든 부모 게임오브젝트 활성화
|
||||
if (durationText != null)
|
||||
{
|
||||
Transform parent = durationText.transform.parent;
|
||||
while (parent != null && parent != transform)
|
||||
{
|
||||
parent.gameObject.SetActive(true);
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 툴팁 표시용 정보 반환
|
||||
/// </summary>
|
||||
public string GetTooltipText()
|
||||
{
|
||||
if (trackedAbnormality?.Data == null) return string.Empty;
|
||||
|
||||
var data = trackedAbnormality.Data;
|
||||
string tooltip = $"<b>{data.abnormalityName}</b>\n";
|
||||
|
||||
if (!data.IsPermanent)
|
||||
{
|
||||
tooltip += $"지속 시간: {trackedAbnormality.RemainingDuration:F1}초\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip += "영구 효과\n";
|
||||
}
|
||||
|
||||
if (data.HasPeriodicEffect)
|
||||
{
|
||||
tooltip += $"주기적 효과: {data.periodicValue:+0}/ {data.periodicInterval}초\n";
|
||||
}
|
||||
|
||||
if (data.HasControlEffect)
|
||||
{
|
||||
tooltip += $"제어 효과: {data.controlType}\n";
|
||||
}
|
||||
|
||||
foreach (var mod in data.statModifiers)
|
||||
{
|
||||
string sign = mod.value >= 0 ? "+" : "";
|
||||
tooltip += $"{mod.statType}: {sign}{mod.value}\n";
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user