yup, found it. Thank you @edc237 - now it’s time for me to choose which of the approaches mentioned in there to go with… I’ll probably go with the first though, let’s see what happens (I’ll backup my project first)
Edit 1: The first approach of this post failed… apparently it did not work AT ALL for me… In fact, removing ‘InventoryUI.Redraw()’ to replace it with the dictionary approach just ensured that I can’t pick anything off the ground, and more importantly, nothing goes into the inventory… So unless Brian hops on board, I’ll try analyze and understand what’s going on
If it helps though, here is my current ‘InventoryUI.cs’ script:
using UnityEngine;
using GameDevTV.Inventories;
using TMPro;
using UnityEngine.Events;
using System.Linq;
using System.Collections.Generic;
namespace GameDevTV.UI.Inventories
{
/// <summary>
/// To be placed on the root of the inventory UI. Handles spawning all the
/// inventory slot prefabs.
/// </summary>
public class InventoryUI : MonoBehaviour
{
// CONFIG DATA
[SerializeField] InventorySlotUI InventoryItemPrefab = null;
// BANK System CONFIG DATA:
[SerializeField] bool isPlayerInventory = true;
[SerializeField] TextMeshProUGUI Title;
// 3 bank <-> Inventory states:
// 'otherInventoryUI' (bank) is open,
// 'otherInventoryUI' (bank) is closed,
// YOU are the 'otherInventoryUI' (bank)
public bool IsOtherInventory => !isPlayerInventory;
public Inventory SelectedInventory => selectedInventory;
[SerializeField] private UnityEvent EnabledEvent;
[SerializeField] private UnityEvent DisabledEvent;
// CACHE
Inventory selectedInventory;
// delete if failed
// InventorySlotUI[] itemUIs; // the items that get transferred, get refreshed
// LIFECYCLE METHODS
private void Awake()
{
// if we are dealing with the player Inventory, set it up (just don't do it for the Players' bank)
if (isPlayerInventory) {
selectedInventory = Inventory.GetPlayerInventory();
selectedInventory.inventoryUpdated += Redraw;
}
}
private void Start()
{
// Redraw the PLAYER INVENTORY, JUST NOT THE BANK!
if (isPlayerInventory) Redraw();
}
// PRIVATE
private void Redraw()
{
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
for (int i = 0; i < selectedInventory.GetSize(); i++)
{
var itemUI = Instantiate(InventoryItemPrefab, transform);
itemUI.Setup(selectedInventory, i);
}
}
// PUBLIC
public bool Setup(GameObject user) {
if (user.TryGetComponent(out selectedInventory)) {
// if the object has an inventory (our bank in this case), set the Selected Inventory Up,
// Subscribe to the Redraw() changes, and then redraw the inventory (to boot it up for the first time):
selectedInventory.inventoryUpdated += Redraw;
Title.text = selectedInventory.name;
Redraw();
return true;
}
return false;
}
private void OnEnable()
{
EnabledEvent?.Invoke();
}
private void OnDisable()
{
DisabledEvent?.Invoke();
}
public void TransferAllInventory()
{
if (selectedInventory != null)
{
selectedInventory.TransferAllInventory(GetOtherInventory());
}
}
private Inventory GetOtherInventory()
{
if (IsOtherInventory) return Inventory.GetPlayerInventory();
// return the FIRST other Inventory it finds (i.e: The bank), or null:
var otherInventoryUI = FindObjectsOfType<InventoryUI>().FirstOrDefault(ui => ui.IsOtherInventory);
//Check to see if it's not null (should never happen), if it's Active, and if the otherInventory's inventory is valid.
if (otherInventoryUI != null && otherInventoryUI.gameObject.activeSelf && otherInventoryUI.SelectedInventory != null)
{
Inventory otherInventory = otherInventoryUI.SelectedInventory;
return otherInventory;
}
return null;
}
}
}
Once we actually get a solution for this, I’ll go also attempt to solve the lag spikes of the shop, from this thread… I just noticed I have these too
Edit 1: I can’t believe it’s been 12 hours, and I still can’t figure out an alternative solution to a stupidly easy algorithm… -_* (WHYYY )
Edit 2: A little bit of an update. I ended up using this Algorithm:
// ------------ TEST AREA: Rewriting the 'Redraw()' algorithm, so that the banking and/or inventory moving stuff around, works faster --------------
int playerInventorySize;
Dictionary<int, InventorySlotUI> inventorySlotCache;
private void Redraw()
{
int sizeCheck = selectedInventory.GetSize();
if (inventorySlotCache == null || playerInventorySize != sizeCheck)
{
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
inventorySlotCache = new Dictionary<int, InventorySlotUI>();
playerInventorySize = sizeCheck;
for (int i = 0; i < playerInventorySize; i++)
{
var itemUI = Instantiate(InventoryItemPrefab, transform);
inventorySlotCache[i] = itemUI;
itemUI.Setup(selectedInventory, i);
}
// Set content window to show top row
transform.localPosition = new Vector3(transform.localPosition.x, 0, transform.localPosition.z);
}
foreach (KeyValuePair<int, InventorySlotUI> inventorySlot in inventorySlotCache)
{
var itemUI = inventorySlot.Value;
itemUI.Setup(selectedInventory, inventorySlot.Key);
}
}
// ---------------------------------------------- END OF TEST --------------------------------------------------------------------------------------
But there’s a major problem. Whilst it works well for Drag and Drop, and clearly it reduces the time to drag and drop stuff around, this algorithm flat out blocks inventory slots from ever being effective for “Click-to-Equip”, after the first time we use the inventory slot. In simple terms, you click it once, it works. You click it again, it’s never going to work, regardless of what you do, and this goes for both the bank and the inventory…
What’s going on here? I’m just trying not to accidentally destroy my entire project to a point of beyond-repair