using UnityEngine; using UnityEngine.UI; using TMPro; /// /// Создаёт UI инвентаря программно с использованием TextMeshPro /// public class InventoryUIBuilder : MonoBehaviour { [Header("Settings")] public int hotbarSlots = 9; public int inventoryRows = 4; public int inventoryCols = 9; [Header("Visual Settings")] public float slotSize = 50f; public float slotSpacing = 4f; public float inventoryPadding = 10f; public float hotbarPadding = 10f; [Header("Colors")] [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(); } public void BuildInventoryUI() { // Создаём или получаем Canvas var canvas = GetComponent(); if (canvas == null) { canvas = gameObject.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 100; gameObject.AddComponent(); } inventoryCanvas = canvas; // Настраиваем EventSystem если нет if (FindObjectOfType() != null || FindObjectsOfType().Length > 0) { // EventSystem уже есть } // Создаём панель инвентаря GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor); inventoryPanelRect = inventoryPanel.GetComponent(); float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2; float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40; // +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.anchoredPosition = Vector2.zero; 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); // Создаём хотбар GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor); hotbarPanelRect = hotbarPanel.GetComponent(); 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.anchoredPosition = new Vector2(0, 15); 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); // Настраиваем InventoryManager InventoryManager.Instance.inventoryPanel = inventoryPanel; InventoryManager.Instance.inventoryCanvas = inventoryCanvas; Debug.Log($"[InventoryUIBuilder] Created {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots"); } GameObject CreatePanel(string name, Transform parent, Color color) { GameObject panel = new GameObject(name); panel.transform.SetParent(parent, false); var rect = panel.AddComponent(); panel.AddComponent().color = color; return panel; } void CreateTitle(Transform parent, string text, Vector2 position) { GameObject titleObj = new GameObject("Title"); titleObj.transform.SetParent(parent, false); var rect = titleObj.AddComponent(); 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); var tmp = titleObj.AddComponent(); tmp.text = text; tmp.fontSize = 18; tmp.alignment = TextAlignmentOptions.Center; 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); gridObj.transform.SetParent(parent, false); var rect = gridObj.AddComponent(); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = offset; rect.offsetMax = -offset; var grid = gridObj.AddComponent(); 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); return gridObj.transform; } Slot[] CreateSlots(Transform parent, string prefix, int startIndex, int count) { var slots = new Slot[count]; for (int i = 0; i < count; i++) { GameObject slotObj = new GameObject(prefix + (startIndex + i)); slotObj.transform.SetParent(parent, false); var rect = slotObj.AddComponent(); rect.sizeDelta = new Vector2(slotSize, slotSize); // Background var bg = slotObj.AddComponent(); bg.color = slotEmptyColor; // Slot компонент var slot = slotObj.AddComponent(); slot.slotIndex = startIndex + i; // Icon GameObject iconObj = new GameObject("Icon"); iconObj.transform.SetParent(slotObj.transform, false); var iconRect = iconObj.AddComponent(); iconRect.anchorMin = Vector2.zero; iconRect.anchorMax = Vector2.one; iconRect.offsetMin = new Vector2(4, 4); iconRect.offsetMax = new Vector2(-4, -4); slot.iconImage = iconObj.AddComponent(); slot.iconImage.preserveAspect = true; slot.iconImage.enabled = false; // Amount panel GameObject amountObj = new GameObject("AmountPanel"); amountObj.transform.SetParent(slotObj.transform, false); var amountRect = amountObj.AddComponent(); 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); slot.amountPanel = amountObj; var amountBg = amountObj.AddComponent(); amountBg.color = new Color(0, 0, 0, 0.7f); GameObject amountTextObj = new GameObject("Text"); amountTextObj.transform.SetParent(amountObj.transform, false); var amountTextRect = amountTextObj.AddComponent(); amountTextRect.anchorMin = Vector2.zero; amountTextRect.anchorMax = Vector2.one; slot.amountText = amountTextObj.AddComponent(); 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(); dragDrop.slot = slot; dragDrop.slotIndex = slot.slotIndex; // Подписка на события слота slot.OnSlotClicked += OnSlotClicked; slots[i] = slot; } return slots; } private int _selectedSlot = -1; private void OnSlotClicked(Slot slot) { // Снимаем выделение с предыдущего if (_selectedSlot >= 0 && _selectedSlot < InventoryManager.Instance.slots.Length) { InventoryManager.Instance.slots[_selectedSlot].SetSelected(false); } // Выделяем новый slot.SetSelected(true); _selectedSlot = slot.slotIndex; Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}"); } /// /// Пересоздать UI (например, при изменении настроек) /// public void Rebuild() { // Удаляем старые панели if (inventoryPanelRect != null) Destroy(inventoryPanelRect.gameObject); if (hotbarPanelRect != null) Destroy(hotbarPanelRect.gameObject); BuildInventoryUI(); } /// /// Показать/скрыть инвентарь /// public void ToggleInventory(bool show) { if (inventoryPanelRect != null) inventoryPanelRect.gameObject.SetActive(show); } }