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

169 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}