Hello everyone, unity and c# study for a few months, I’m developing an inventory system made with scriptable object; at the moment I’m at a dead end:
inventory works, prefabricated weapons are instantiated to the player, when I collect an item it is loaded into the inventory UI, but the onClickCallBack is not assigned to the slot and the item is unusable. You have some advice.
Thank you thank you
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName ="Scriptable Objects/Inventory System/Inventory")]
public class Inventory : ScriptableObject
{
// pickup item
public static Inventory inventory;
[SerializeField] private InventoryUI inventoryUIPrefab;
private InventoryUI _inventoryUI;
private InventoryUI inventoryUI
{
get
{
if(!_inventoryUI)
{
_inventoryUI = Instantiate(inventoryUIPrefab, playerEquipment.GetUIParent());
}
return _inventoryUI;
}
}
public Dictionary<InventoryItem, int> itemToCountMap = new Dictionary<InventoryItem, int>();
public List<InventoryItemWrapper> items = new List<InventoryItemWrapper>(); // pickup item here
private PlayerEquipmentController playerEquipment;
public void InitInventory(PlayerEquipmentController playerEquipment)
{
this.playerEquipment = playerEquipment;
for(int i = 0; i < items.Count; i++)
{
itemToCountMap.Add(items[i].GetItem(), items[i].GetItemCount());
}
}
public void OpenInventory()
{
inventoryUI.gameObject.SetActive(true);
inventoryUI.InitInventoryUI(this);
}
public void AssignItem(InventoryItem item)
{
item.AssignItemToPlayer(playerEquipment);
}
public Dictionary<InventoryItem, int> GetAllItemsMap()
{
return itemToCountMap;
}
public void RemoveItem(InventoryItem item, int count)
{
int currentItemCount;
if(itemToCountMap.TryGetValue(item, out currentItemCount))
{
itemToCountMap[item] = currentItemCount - count;
if(currentItemCount - count <= 0)
{
inventoryUI.DestroySlot(item);
}
else
{
inventoryUI.UpdateSlot(item, currentItemCount - count);
}
}
else
{
Debug.Log(string.Format("Cant Remove {0}. This item is not in the inventory"));
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryUI : MonoBehaviour
{
[SerializeField] private Transform slotsParent;
[SerializeField] private InventorySlot slotPrefab;
private Dictionary<InventoryItem, InventorySlot> itemToSlotMap = new Dictionary<InventoryItem, InventorySlot>();
public PlayerPIckUp playerPIckUp;
public static InventoryUI inventoryUI;
public void InitInventoryUI(Inventory inventory)
{
var itemsMap = inventory.GetAllItemsMap();
foreach(var kvp in itemsMap)
{
CreateOrUpdateSlot(inventory, kvp.Key, kvp.Value);
}
}
public void CreateOrUpdateSlot(Inventory inventory, InventoryItem item, int itemCount)
{
if (itemCount != 0)
{
// if inventory does not contain the item
if (!itemToSlotMap.ContainsKey(item))
{
var slot = CreateSlot(inventory, item, itemCount);
itemToSlotMap.Add(item, slot);
}
else
{
UpdateSlot(item, itemCount);
}
}
}
public void UpdateSlot(InventoryItem item, int itemCount)
{
itemToSlotMap[item].UpdateSlotCount(itemCount);
}
public InventorySlot CreateSlot(Inventory inventory, InventoryItem item, int itemCount)
{
var slot = Instantiate(slotPrefab,slotsParent);
slot.InitSlotVisualization(item.GetSprite(), item.GetName(), itemCount);
slot.AssignSlotButtonCallBack(() => inventory.AssignItem(item));
return slot;
}
public void DestroySlot(InventoryItem item)
{
Destroy(itemToSlotMap[item].gameObject);
itemToSlotMap.Remove(item);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class InventorySlot : MonoBehaviour
{
[SerializeField] public Image emptySlot;
[SerializeField] private Image itemImage;
[SerializeField] private TextMeshProUGUI itemNameText;
[SerializeField] private TextMeshProUGUI itemCountText;
public Button slotButton;
public void InitSlotVisualization(Sprite itemSprite, string itemName, int itemCount)
{
itemImage.sprite = itemSprite;
itemNameText.text = itemName;
UpdateSlotCount(itemCount);
}
public void UpdateSlotCount(int itemCount)
{
itemCountText.text = itemCount.ToString();
}
public void AssignSlotButtonCallBack(System.Action onClickCallBack)
{
slotButton.onClick.AddListener(() => onClickCallBack());
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// il problema sempre essere alla riga 61 di inventory e di conseguenza l'errore si trasmette alla riga 30 di inventory slot
public class PlayerPIckUp : MonoBehaviour // raccoglie un oggetto lo instanzia nella UI ma poi rimane inutilizzabile per il mancato callback
{
[SerializeField] public InventoryItem item;
public int itemCount;
private InventoryUI inventoryUI;
private Inventory inventory;
private InventorySlot inventorySlot;
void Start()
{
inventoryUI = FindObjectOfType<InventoryUI>();
inventory = FindObjectOfType<Inventory>();
}
public void OnTriggerStay(Collider other)
{
var player = CompareTag("Player");
if(player = true && Input.GetButtonDown("Fire2"))
{
inventoryUI.CreateSlot(inventory, item, itemCount);
this.gameObject.SetActive(false);
}
}
}