And… I’m stuck. Quite badly tbh:
After finally getting the title to show up (check step 5 below. You’ll see the debugs to see what I went through to try and get that title right… it was a disaster ), I got 2 problems now (and one of them has been going on for a while, it’s hard to ignore now). I’ll name them “a” and “b”
a. (This is the bad one) - unless I save and quit my game, the visible UI will be mixed between my bank, and the pickup UI I’m trying to create. The information is correct, but the bank will, for some reason, try to open up my ‘PickupInventory’ UI instead of my ‘Bank’ UI, ever since I introduced this system today (unless I save and quit, and then return to the game, that is).
I have no idea why any of this is happening, but it’s also why my shop sometimes needs to be re-opened to work, why my money won’t always show the accurate value, why my quiver won’t show the arrows unless 50% of the time, etc… I’ll return to fixing this bug as soon as this topic is over. It has to be addressed!
b. The UI for the Pickup Inventory I’m trying to setup won’t properly refresh for some reason, and that’s what this entire comment will be all about. It’s about the steps I took so far to reach where I currently am, and to help me brainstorm this problem and get it fixed
Let’s start by addressing the second problem first, to stay on topic. Here’s a rundown of exactly what I did (mind you, you need to follow @Brian_Trotter 's merge course, along with his Inventory Containers from his tips and tricks, to understand what’s going on here)
- In ‘PlayerFreeLookState.cs’, I went ahead and updated my Pickup to open the UI properly:
private void InputReader_HandlePickupEvent()
{
// if (stateMachine.PickupFinder.GetNearestPickup() != null)
if (stateMachine.PickupFinder.FindNearestTarget())
{
if (AnimalMountManager.isOnAnimalMount)
{
// No pickup handling from this script when the player is mounting the animal is allowed.
// It will be handled elsewhere, or maybe even not handled at all
return;
}
// stateMachine.SwitchState(new PlayerPickupState(stateMachine, stateMachine.PickupFinder.CurrentTarget));
// I'm replacing the current Pickup System above, with a brand new Inventory-based Pickup System.
// Player-wise, this will be significantly easier to deal with, and faster for the players to use as well,
// so it's a win-win situation (Check below)
// There is only one component in the entire game that's allowed to have a tag of 'PlayerPickupInventory', so this approach is pretty safe
stateMachine.SwitchState(new PlayerPickupInventoryState(stateMachine, GameObject.FindGameObjectWithTag("PlayerPickupInventory").GetComponent<OtherInventory>()));
}
}
- I created the required state, and called it ‘PlayerPickupInventoryState.cs’, a solution to open up the Pickup UI that I created:
using System.Collections;
using System.Collections.Generic;
using GameDevTV.Inventories;
using RPG.States.Player;
using UnityEngine;
public class PlayerPickupInventoryState : PlayerBaseState
{
private OtherInventory pickupInventory;
public PlayerPickupInventoryState(PlayerStateMachine stateMachine, OtherInventory pickupInventory) : base(stateMachine)
{
this.pickupInventory = pickupInventory;
}
public override void Enter()
{
Debug.Log($"Player entered 'PlayerPickupInventoryState'");
pickupInventory.OpenPickupInventory(stateMachine);
}
public override void Tick(float deltaTime) {}
public override void Exit()
{
Debug.Log($"Player exited 'PlayerPickupInventoryState");
}
}
as you can see, it’s quite simple. Opening it is handled here, and closing it will be handled at the ‘Quit button’ in my game inspector
- in ‘OtherInventory.cs’ (It’s an old creation of mine, to compensate for having a bank in my game. Again, follow this tutorial to get the idea), I created this function, specifically to open up the bank:
public void OpenPickupInventory(PlayerStateMachine player)
{
player.GetComponent<PickupAction>().StartPickupAction
(
() =>
{
// Unlike the banking action, you don't need a transform here. You just need to open the inventory, and that's it!
// (whether there's a Pickup Item or not is handled in 'PlayerFreeLookState.cs', where we originally access this part of the code from)
pickupInventoryThirdPersonShowHideUI.ShowPickupInventory(GameObject.FindWithTag("PlayerPickupInventory").GetComponent<OtherInventory>().gameObject);
}
);
}
As you can tell, this is attached to something called ‘PickupInventory’ (check the before-the-last image of this comment to see what I’m talking about), with a script called ‘ThirdPersonShowHideUI’ attached to it, that has a connection to a ‘PlayerPickupInventory’-tagged GameObject on the hierarchy, which… has an ‘OtherInventory’ on it, so we can tell it how many slots the ‘PickupInventory’ UI should have
- Here is the ‘ShowPickupInventory’ from my ‘ThirdPersonShowHideUI.cs’ script:
public void ShowPickupInventory(GameObject pickupInventory)
{
// Displaying the Pickup Inventory, which slightly differs from 'ShowOtherInventory', because this isn't a bank anymore
UIContainer.SetActive(true);
otherInventoryContainer.SetActive(true);
otherInventoryUI.SetupPickupInventory(pickupInventory);
}
Here, we are setting up the inventory, but also where my problem is most likely at, unless I missed out on something. Moving on to step 5:
- [THIS STEP IS A COMPLETE DISASTER. I SUGGEST YOU HOLD BACK ON IT FOR NOW] ‘OtherInventoryUI’ is essentially the script called ‘InventoryUI.cs’, and here is where I try to setup the UI appropriately, using a ‘SetupPickupInventory()’ function:
public bool SetupPickupInventory(GameObject pickupInventoryUser)
{
if (pickupInventoryUser.TryGetComponent(out selectedInventory)) // Confirms that it is indeed the player calling this UI
{
selectedInventory.inventoryUpdated += PickupRedraw; // Refresh the Player Inventory
if (PickupTitle != null)
{
var textMeshproComponent = PickupTitle.GetComponent<TextMeshProUGUI>();
if (textMeshproComponent != null)
{
PickupTitle.text = textMeshproComponent.text;
}
else
{
Debug.Log($"TextMeshProUGUI component is missing on PickupTitle GameObject");
}
}
else
{
Debug.Log($"PickupTitle is not assigned in the inspector");
}
Redraw();
return true;
}
else return false;
}
and a ‘PickupRedraw()’ function:
private void PickupRedraw()
{
// Redrawing the Inventory from scratch, when the pickup happens
foreach (Transform child in this.transform)
{
Destroy(child.gameObject);
}
// Find items within the Pickup Radius
Collider[] hitColliders = Physics.OverlapSphere(selectedInventory.transform.position, pickupRadius);
for (int i = 0; i < hitColliders.Length; i++)
{
var pickupItem = hitColliders[i].GetComponent<Pickup>();
if (pickupItem != null)
{
var itemUI = Instantiate(InventoryItemPrefab, transform);
itemUI.Setup(selectedInventory, i);
}
}
}
However, I’m not extremely familiar with what exactly is going on in step 5, hence why I’m here seeking help
- I also created this script, called ‘PickupAction.cs’, so that the ‘IAction.cs’ Interface can use it, and actually get the player to open up the UI, as follows:
using System.Collections;
using System.Collections.Generic;
using RPG.Core;
using UnityEngine;
namespace RPG.Pickups {
public class PickupAction : MonoBehaviour, IAction
{
System.Action callback;
bool isPickingUp;
public void StartPickupAction(System.Action callback)
{
this.callback = callback;
GetComponent<ActionSchedular>().StartAction(this);
isPickingUp = true;
}
public void Update()
{
if (isPickingUp)
{
callback?.Invoke(); // This is how you open up the Pickup Inventory
Debug.Log($"Player Pickup Inventory opened through update");
isPickingUp = false;
return; // You don't want to forget this line, unless you want your computer to explode...! (THIS IS AN UPDATE YOU SICK BASTARD!)
}
else return; // Explosion-proof code
}
public void Cancel()
{
ThirdPersonShowHideUI.CloseAllWindows();
isPickingUp = false;
}
}
}
- If I forgot to mention this earlier, the closing of that UI is handled through the Quit button, so we don’t need to worry about that for now (if you need it, just ask)
As for the Unity Inspector itself, I created these to help me out:
7a. Place ‘PickupAction.cs’, the script from step 6, on my player
7b. Created this ‘PickupInventory’ (a copy of my functional bank right above it), which is what the Pickup Inventory UI should open up to, and set it up as follows:
7c. I also created this ‘PlayerPickupInventory’, which holds my ‘OtherInventory’ (and no saving system on this one. I’m not saving the pickups if they can be accumulated off the ground. Let it be as is), so the UI in step 7b knows how many slots there are, and how to work with it:
I think that’s about all the modifications done. I tried not to do anything crazy to my original code, out of fear of mistakes
But my question now is, regarding problem ‘b’ at the top of this specific comment, why can’t I get the UI to place the items around the player, when he pressed the ‘P’ key, to show up in the UI Slots?
The goal is to get them to show up in the form of items in an inventory, where you can only press to take them from that inventory to yours, and no way around, and then destroy them from the game world when they’re taken
I’m sorry if that sounds like a crazy concept, or it’s too much to take in, but it’s essential to make my game pickup system easier
The goal is to replace the current pickup system, mainly to deal with a few frustrations that I personally have with it
I have a feeling that something in the logic is flawed somewhere, and more likely than not, I did something (or things) wrong, and I need a set of fresh eyes to help me. Please help me out, I’m not extremely familiar with UI-related coding or work in general (just trying to use what I have so far)
and… when I return to the original system after all these crazy changes are done, there’s a duplication bug (I did something terribly wrong I suppose)