fix чать инвенторя

This commit is contained in:
jze9
2026-04-16 01:51:46 +05:00
parent 057f5d3d1e
commit 6c3f72385e
35 changed files with 18160 additions and 14313 deletions

View File

@@ -3,7 +3,9 @@ using UnityEngine.UI;
using TMPro;
/// <summary>
/// Создаёт UI инвентаря программно с использованием TextMeshPro
/// Создаёт UI инвентаря программно.
/// Вызывается ТОЛЬКО из редакторных инструментов (InventorySceneSetup, PlayerBuilderTool).
/// Никакого runtime-создания: Start() отсутствует.
/// </summary>
public class InventoryUIBuilder : MonoBehaviour
{
@@ -22,138 +24,113 @@ public class InventoryUIBuilder : MonoBehaviour
[SerializeField] private Color inventoryPanelColor = new Color(0.15f, 0.15f, 0.15f, 0.95f);
[SerializeField] private Color hotbarPanelColor = new Color(0.1f, 0.1f, 0.1f, 0.9f);
[SerializeField] private Color slotEmptyColor = new Color(0.25f, 0.25f, 0.25f, 0.8f);
[SerializeField] private Color slotFilledColor = new Color(0.35f, 0.35f, 0.35f, 0.95f);
[Header("Container References")]
public RectTransform inventoryPanelRect;
public RectTransform hotbarPanelRect;
public Canvas inventoryCanvas;
void Start()
{
// Проверяем, не запущен ли уже BuildInventoryUI
if (InventoryManager.Instance != null &&
InventoryManager.Instance.slots != null &&
InventoryManager.Instance.slots.Length > 0)
{
Debug.Log("[InventoryUIBuilder] UI already built, skipping");
return;
}
// Созданные слоты — читаются редакторным инструментом после BuildInventoryUI()
[SerializeField] private Slot[] _inventorySlots;
[SerializeField] private Slot[] _hotbarSlots;
BuildInventoryUI();
}
public Slot[] GetInventorySlots() => _inventorySlots;
public Slot[] GetHotbarSlots() => _hotbarSlots;
// ── Построение UI ────────────────────────────────────────────────────────
public void BuildInventoryUI()
{
// Создаём или получаем Canvas
// Получаем или добавляем Canvas
var canvas = GetComponent<Canvas>();
if (canvas == null)
{
canvas = gameObject.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 100;
gameObject.AddComponent<GraphicRaycaster>();
}
inventoryCanvas = canvas;
// Настраиваем EventSystem если нет
if (FindObjectOfType<TMPro.TMP_InputField>() != null || FindObjectsOfType<TMPro.TextMeshProUGUI>().Length > 0)
{
// EventSystem уже есть
}
// Создаём панель инвентаря
// Панель инвентаря
GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor);
inventoryPanelRect = inventoryPanel.GetComponent<RectTransform>();
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40; // +40 для заголовка
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40;
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
inventoryPanelRect.pivot = new Vector2(0.5f, 0.5f);
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
inventoryPanelRect.pivot = new Vector2(0.5f, 0.5f);
inventoryPanelRect.anchoredPosition = Vector2.zero;
inventoryPanelRect.sizeDelta = new Vector2(inventoryWidth, inventoryHeight);
inventoryPanelRect.sizeDelta = new Vector2(inventoryWidth, inventoryHeight);
// Заголовок
CreateTitle(inventoryPanel.transform, "Инвентарь", new Vector2(0, inventoryHeight / 2 - 20));
// Сетка инвентаря (4x9 = 36 слотов)
float gridHeight = inventoryRows * (slotSize + slotSpacing);
var inventoryGrid = CreateGrid(
inventoryPanel.transform,
"InventoryGrid",
inventoryCols,
inventoryRows,
slotSize,
slotSpacing,
new Vector2(inventoryPadding, inventoryPadding + 30)
);
InventoryManager.Instance.slots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
inventoryPanel.transform, "InventoryGrid",
inventoryCols, inventoryRows,
slotSize, slotSpacing,
new Vector2(inventoryPadding, inventoryPadding + 30));
// Создаём хотбар
_inventorySlots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
// Хотбар
GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor);
hotbarPanelRect = hotbarPanel.GetComponent<RectTransform>();
float hotbarWidth = hotbarSlots * (slotSize + slotSpacing) + hotbarPadding * 2;
hotbarPanelRect.anchorMin = new Vector2(0.5f, 0f);
hotbarPanelRect.anchorMax = new Vector2(0.5f, 0f);
hotbarPanelRect.pivot = new Vector2(0.5f, 0f);
hotbarPanelRect.anchorMin = new Vector2(0.5f, 0f);
hotbarPanelRect.anchorMax = new Vector2(0.5f, 0f);
hotbarPanelRect.pivot = new Vector2(0.5f, 0f);
hotbarPanelRect.anchoredPosition = new Vector2(0, 15);
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
var hotbarGrid = CreateGrid(
hotbarPanel.transform,
"HotbarGrid",
hotbarSlots,
1,
slotSize,
slotSpacing,
new Vector2(hotbarPadding, hotbarPadding)
);
InventoryManager.Instance.hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
hotbarPanel.transform, "HotbarGrid",
hotbarSlots, 1,
slotSize, slotSpacing,
new Vector2(hotbarPadding, hotbarPadding));
// Настраиваем InventoryManager
InventoryManager.Instance.inventoryPanel = inventoryPanel;
InventoryManager.Instance.inventoryCanvas = inventoryCanvas;
_hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
Debug.Log($"[InventoryUIBuilder] Created {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots");
Debug.Log($"[InventoryUIBuilder] Built {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots");
}
// ── Вспомогательные методы ────────────────────────────────────────────────
GameObject CreatePanel(string name, Transform parent, Color color)
{
GameObject panel = new GameObject(name);
var panel = new GameObject(name);
panel.transform.SetParent(parent, false);
var rect = panel.AddComponent<RectTransform>();
panel.AddComponent<RectTransform>();
panel.AddComponent<Image>().color = color;
return panel;
}
void CreateTitle(Transform parent, string text, Vector2 position)
{
GameObject titleObj = new GameObject("Title");
var titleObj = new GameObject("Title");
titleObj.transform.SetParent(parent, false);
var rect = titleObj.AddComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(1, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(1, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.anchoredPosition = position;
rect.sizeDelta = new Vector2(-20, 30);
rect.sizeDelta = new Vector2(-20, 30);
var tmp = titleObj.AddComponent<TextMeshProUGUI>();
tmp.text = text;
tmp.fontSize = 18;
tmp.text = text;
tmp.fontSize = 18;
tmp.alignment = TextAlignmentOptions.Center;
tmp.color = Color.white;
tmp.color = Color.white;
}
Transform CreateGrid(Transform parent, string name, int cols, int rows, float cellSize, float spacing, Vector2 offset)
{
GameObject gridObj = new GameObject(name);
var gridObj = new GameObject(name);
gridObj.transform.SetParent(parent, false);
var rect = gridObj.AddComponent<RectTransform>();
@@ -163,13 +140,13 @@ public class InventoryUIBuilder : MonoBehaviour
rect.offsetMax = -offset;
var grid = gridObj.AddComponent<GridLayoutGroup>();
grid.cellSize = new Vector2(cellSize, cellSize);
grid.spacing = new Vector2(spacing, spacing);
grid.startCorner = GridLayoutGroup.Corner.UpperLeft;
grid.startAxis = GridLayoutGroup.Axis.Horizontal;
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
grid.cellSize = new Vector2(cellSize, cellSize);
grid.spacing = new Vector2(spacing, spacing);
grid.startCorner = GridLayoutGroup.Corner.UpperLeft;
grid.startAxis = GridLayoutGroup.Axis.Horizontal;
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
grid.constraintCount = cols;
grid.padding = new RectOffset(0, 0, 0, 0);
grid.padding = new RectOffset(0, 0, 0, 0);
return gridObj.transform;
}
@@ -180,22 +157,21 @@ public class InventoryUIBuilder : MonoBehaviour
for (int i = 0; i < count; i++)
{
GameObject slotObj = new GameObject(prefix + (startIndex + i));
var slotObj = new GameObject(prefix + (startIndex + i));
slotObj.transform.SetParent(parent, false);
var rect = slotObj.AddComponent<RectTransform>();
rect.sizeDelta = new Vector2(slotSize, slotSize);
// Background
var bg = slotObj.AddComponent<Image>();
bg.color = slotEmptyColor;
// Slot компонент
var slot = slotObj.AddComponent<Slot>();
slot.slotIndex = startIndex + i;
slot.slotIndex = startIndex + i;
slot.slotBackground = bg;
// Icon
GameObject iconObj = new GameObject("Icon");
// Иконка
var iconObj = new GameObject("Icon");
iconObj.transform.SetParent(slotObj.transform, false);
var iconRect = iconObj.AddComponent<RectTransform>();
iconRect.anchorMin = Vector2.zero;
@@ -206,41 +182,37 @@ public class InventoryUIBuilder : MonoBehaviour
slot.iconImage.preserveAspect = true;
slot.iconImage.enabled = false;
// Amount panel
GameObject amountObj = new GameObject("AmountPanel");
// Количество
var amountObj = new GameObject("AmountPanel");
amountObj.transform.SetParent(slotObj.transform, false);
var amountRect = amountObj.AddComponent<RectTransform>();
amountRect.anchorMin = Vector2.one;
amountRect.anchorMax = Vector2.one;
amountRect.pivot = new Vector2(1, 0);
amountRect.anchorMin = Vector2.one;
amountRect.anchorMax = Vector2.one;
amountRect.pivot = new Vector2(1, 0);
amountRect.anchoredPosition = new Vector2(-2, 2);
amountRect.sizeDelta = new Vector2(22, 22);
amountRect.sizeDelta = new Vector2(22, 22);
slot.amountPanel = amountObj;
var amountBg = amountObj.AddComponent<Image>();
amountBg.color = new Color(0, 0, 0, 0.7f);
amountObj.AddComponent<Image>().color = new Color(0, 0, 0, 0.7f);
GameObject amountTextObj = new GameObject("Text");
var amountTextObj = new GameObject("Text");
amountTextObj.transform.SetParent(amountObj.transform, false);
var amountTextRect = amountTextObj.AddComponent<RectTransform>();
amountTextRect.anchorMin = Vector2.zero;
amountTextRect.anchorMax = Vector2.one;
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
slot.amountText.fontSize = 14;
slot.amountText.alignment = TextAlignmentOptions.Right;
slot.amountText.color = Color.white;
slot.amountText.fontStyle = FontStyles.Bold;
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
slot.amountText.fontSize = 14;
slot.amountText.alignment = TextAlignmentOptions.Right;
slot.amountText.color = Color.white;
slot.amountText.fontStyle = FontStyles.Bold;
// Применяем настройки через сеттер
slot.amountPanel.SetActive(false);
slot.slotBackground = bg;
// Drag & Drop
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
dragDrop.slot = slot;
dragDrop.slot = slot;
dragDrop.slotIndex = slot.slotIndex;
// Подписка на события слота
slot.OnSlotClicked += OnSlotClicked;
slots[i] = slot;
@@ -249,43 +221,38 @@ public class InventoryUIBuilder : MonoBehaviour
return slots;
}
// ── Выделение слота (runtime) ─────────────────────────────────────────────
private int _selectedSlot = -1;
private void OnSlotClicked(Slot slot)
{
// Снимаем выделение с предыдущего
if (_selectedSlot >= 0 && _selectedSlot < InventoryManager.Instance.slots.Length)
{
InventoryManager.Instance.slots[_selectedSlot].SetSelected(false);
}
if (_selectedSlot >= 0 && _inventorySlots != null && _selectedSlot < _inventorySlots.Length)
_inventorySlots[_selectedSlot].SetSelected(false);
// Выделяем новый
slot.SetSelected(true);
_selectedSlot = slot.slotIndex;
Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}");
}
/// <summary>
/// Пересоздать UI (например, при изменении настроек)
/// </summary>
// ── Утилиты ───────────────────────────────────────────────────────────────
public void Rebuild()
{
// Удаляем старые панели
if (inventoryPanelRect != null)
Destroy(inventoryPanelRect.gameObject);
if (hotbarPanelRect != null)
Destroy(hotbarPanelRect.gameObject);
_inventorySlots = null;
_hotbarSlots = null;
BuildInventoryUI();
}
/// <summary>
/// Показать/скрыть инвентарь
/// </summary>
public void ToggleInventory(bool show)
{
if (inventoryPanelRect != null)
inventoryPanelRect.gameObject.SetActive(show);
}
}
}