Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/UI/SettlementUIInventoryDisplay.cs

169 lines
5.8 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using Base;
using Entity;
using Item;
using Prefab;
using UnityEngine;
namespace UI
{
/// <summary>
/// 通用的结算UI组件用于在指定时间内动态显示指定库存中的物品图标。
/// </summary>
public class SettlementUIInventoryDisplay : MonoBehaviour, ITickUI
{
[Tooltip("用于显示物品图标的父Transform")]
public Transform showIcon;
[Tooltip("物品图标的Prefab")]
public ImagePrefabUI iconPrefab;
private int index;
private float timer;
private float totalTime;
private List<ItemResource> itemsToDisplay = new();
/// <summary>
/// 开始显示物品流程。
/// </summary>
/// <param name="time">显示所有物品所需总时间。</param>
/// <param name="inventorySlotProvider">提供物品槽位的数组。</param>
public void StartShow(float time, InventorySlot[] inventorySlotProvider)
{
// 在开始新显示流程前先确保移除旧的TickUI注册
Clock.RemoveTickUI(this);
// 清除当前显示区域中的所有旧图标
foreach (Transform iconTransform in showIcon)
{
Destroy(iconTransform.gameObject);
}
// 如果没有物品或获取物品失败,则直接返回。
if (inventorySlotProvider == null || !inventorySlotProvider.Any())
{
Debug.LogWarning("SettlementUIInventoryDisplay: 没有物品可显示或库存提供者返回空。");
return;
}
totalTime = time;
timer = 0;
index = 0;
itemsToDisplay.Clear();
// 将所有InventorySlot中的物品及其数量展开添加到待显示列表中
foreach (var inventorySlot in inventorySlotProvider)
{
// 确保物品资源不为空
if (inventorySlot.Item != null)
{
for (var i = 0; i < inventorySlot.Quantity; i++)
{
itemsToDisplay.Add(inventorySlot.Item);
}
}
}
// 如果填充后依然没有物品,也提前返回
if (itemsToDisplay.Count == 0)
{
Debug.LogWarning("SettlementUIInventoryDisplay: 处理库存槽位后未找到有效物品。");
return;
}
// totalTime 有效性检查
if (totalTime <= 0f)
{
Debug.LogWarning("SettlementUIInventoryDisplay: 总显示时间为零或负数。立即显示所有物品。");
ShowAllImmediately();
return;
}
// 确保只有当有物品且需要动态显示时才注册到 Clock
Clock.AddTickUI(this);
}
/// <summary>
/// 每帧更新UI显示逻辑。
/// </summary>
public void TickUI()
{
// 如果没有物品可显示,或所有物品都已显示,直接停止计时。
if (itemsToDisplay.Count == 0 || index >= itemsToDisplay.Count)
{
Clock.RemoveTickUI(this);
return;
}
timer += Time.deltaTime;
// 计算当前时间点应该已经显示了多少物品。
// Math.Min确保end不会超过物品总数。
var end = Math.Min(itemsToDisplay.Count, (int)(itemsToDisplay.Count * timer / totalTime));
// 循环实例化从上次显示位置到当前应该显示位置之间的物品图标
for (; index < end; index++)
{
var item = itemsToDisplay[index];
// 确保物品不为空
if (item == null)
{
Debug.LogWarning($"SettlementUIInventoryDisplay: 索引 {index} 处的物品为空,跳过图标创建。");
continue;
}
// 实例化图标Prefab并设置父Transform
var obj = Instantiate(iconPrefab, showIcon);
// 设置图标图片。item.Icon?[0] 确保在Icon为null时不报错
obj.Icon = item.Icon?[0];
obj.gameObject.name = $"Icon_{item.Name}_{index}";
}
}
/// <summary>
/// 立即显示所有待显示的物品图标,并停止计时器更新。
/// </summary>
public void ShowAllImmediately()
{
// 停止TickUI的更新防止同步出现动态显示
Clock.RemoveTickUI(this);
if (itemsToDisplay.Count == 0)
{
return;
}
if (index >= itemsToDisplay.Count)
{
return;
}
// 从当前 index 开始,显示所有剩余物品
for (; index < itemsToDisplay.Count; index++)
{
var item = itemsToDisplay[index];
if (item == null)
{
Debug.LogWarning($"SettlementUIInventoryDisplay: 立即显示时索引 {index} 处的物品为空,跳过图标创建。");
continue;
}
// 实例化图标Prefab并设置父Transform
var obj = Instantiate(iconPrefab, showIcon);
obj.Icon = item.Icon?[0];
obj.gameObject.name = $"Icon_{item.Name}_{index}_Immediate";
}
// 确保 index 达到最大
index = itemsToDisplay.Count;
}
private void OnDestroy()
{
// 确保在组件销毁时从Clock中移除注册
Clock.RemoveTickUI(this);
}
}
}