[FOR THE NEXT 20 REPLIES, I HAVE SOMEHOW ELIMINATED EVERY SINGLE PROBLEM MENTIONED… JUST SKIP TO 564 ONWARDS, IF I HAVE SOMETHING I’LL BRING IT UP THERE]
BUT… THERE’S A SMALL PROBLEM AT THE END OF REPLY NUMBER 563, THE VERY VERY VERY VERY LAST SENTENCE [EDIT 4]
[MAJOR PERFORMANCE ISSUE IS BACK, LAST LINE OF THE NEXT COMMENT… APART FROM THAT PROBLEM, I FIXED THE BANK. RIGHT NOW I’M JUST DOCUMENTING THE STEPS TAKEN TO FIX THIS. MY PROBLEMS (Compared to the Bank, they are MINOR) ARE IN THE NEXT COMMENT]
last thing I remember, was I got the player capable of interacting and opening the bank UI (however I temporarily commented out the idea back then, because somehow, it messes with the cancellation of the Construction… I’ll figure this out on my own)
- In the Action Map, I created a button to interact with the bank, and assigned it in ‘InputReader.cs’, as follows:
public bool IsBanking {get; private set;}
public event Action BankEvent;
public void OnBank(InputAction.CallbackContext context)
{
if (context.performed) {
IsBanking = true;
BankEvent?.Invoke();
}
else if (context.canceled) IsBanking = false;
}
- In ‘PlayerFreeLookState.cs’, I got the proper event (for my understanding, I like to think of events as heart pulses. For a pulse (frame), you perform some important but intense calculations, and then go quiet until necessary again… That’s just my way of going through these ideas) subscriptions, so we can subscribe and unsubscribe when necessary:
// in 'PlayerFreeLookState.Enter()'
stateMachine.InputReader.BankEvent += InputReader_HandleBankingEvent;
// in 'PlayerFreeLookState.Exit()'
stateMachine.InputReader.BankEvent -= InputReader_HandleBankingEvent;
// and... the function that switches the State Machine:
private void InputReader_HandleBankingEvent()
{
if (stateMachine.BankFinder.GetNearestBank()) {
stateMachine.SwitchState(new PlayerBankingState(stateMachine, stateMachine.BankFinder.GetNearestBank()));
}
}
// I commented this function out for the time being, until I figure out why it's messing with my Construction System, since that system entirely deactivates the State Machine
next, I created a ‘PlayerBankingState’ as follows:
using UnityEngine;
using GameDevTV.Inventories;
using RPG.States.Player;
public class PlayerBankingState : PlayerBaseState
{
private OtherInventory target;
public PlayerBankingState(PlayerStateMachine stateMachine, OtherInventory otherInventory) : base(stateMachine)
{
this.target = otherInventory;
}
public override void Enter()
{
Debug.Log("Player Entered Banking State");
target.OpenBank(stateMachine);
target.OtherInventoryClosed += OnOtherInventoryClosed;
}
public override void Tick(float deltaTime) {}
public override void Exit()
{
target.OtherInventoryClosed -= OnOtherInventoryClosed;
Debug.Log("Player Exited Banking State");
}
public void OnOtherInventoryClosed()
{
SetLocomotionState();
Debug.Log("Banking State Closed");
}
}
which… refers to ‘OtherInventory.cs’, as follows:
using System.Linq;
using GameDevTV.UI;
using GameDevTV.UI.Inventories;
using RPG.Core;
using RPG.States.Player;
using UnityEngine;
namespace GameDevTV.Inventories {
[RequireComponent(typeof(Inventory))]
public class OtherInventory : MonoBehaviour, ITarget//, IRaycastable
{
private ShowHideUI showHideUI;
[SerializeField] GameObject bankUIToOpen;
private void Awake() {
showHideUI = FindObjectsOfType<ShowHideUI>().FirstOrDefault(s => s.HasOtherInventory);
}
/* public CursorType GetCursorType() {
return CursorType.Pickup;
}
public bool HandleRaycast(PlayerController callingController) {
if (showHideUI == null) return false;
if (Input.GetMouseButtonDown(0)) {
callingController.GetComponent<BankAction>().StartBankAction(transform, () =>
{ showHideUI.ShowOtherInventory(gameObject); });
}
return true;
} */
// ALL OF THE FOLLOWING FUNCTIONS ARE TESTS:
public void OpenBank(PlayerStateMachine player)
{
// If the bank is open, return:
if (bankUIToOpen.activeSelf) return;
// Set the bank UI to activate:
bankUIToOpen.SetActive(true);
// Refresh the bank UI:
InventoryUI bankUI = bankUIToOpen.GetComponent<InventoryUI>();
if (bankUI != null)
{
bankUI.Setup(this.gameObject);
}
else Debug.Log("Bank UI does not have InventoryUI Component Attached");
}
public event System.Action OtherInventoryClosed;
public void CloseOtherInventory()
{
OtherInventoryClosed?.Invoke();
}
public bool IsValid()
{
return Vector3.Distance(GameObject.FindWithTag("Player").transform.position, transform.position) < 4.0f;
// I hard-coded 4.0f because that's a decent distance, anything slightly more or less was troublesome...
}
}
}
oh, and this was also introduced in ‘PlayerStateMachine.cs’:
[field: SerializeField] public BankFinder BankFinder {get; private set;}
and in ‘PlayerStateMachine.OnValidate()’:
if (BankFinder == null) BankFinder = GetComponentInChildren<BankFinder>();
obviously for this to work, you must have a ‘BankFinder’ script on an empty (ok not necessarily empty, but it exists) gameObject, under your player gameObject, with a Sphere trigger activated (to detect the bank item)
along with the usual BankFinder Sphere Trigger on the Player
Generally, this algorithm successfully gets the bank to show up the UI with no issues (except that it messes with my Construction System somehow, but I’ll figure this out later on my own). However, I can’t properly interact with the bank UI, and I can’t figure out why… (each slot outputs “0 was clicked once”, a debugger I once placed in the inventory to ensure each slot was unique… For the bank though, this isn’t the case for some reason. UI Shows up, but nothing works), and once it opens, the “Close” button won’t work either (which is expected, because it isn’t properly setup yet)
Edit 1: I made some significant improvements since I wrote this comment, although frankly speaking there was a lot of copy-pasting of code, and I didn’t understand much of what I was doing, but I tried it anyway… Here’s what I did (and I think this has permanently fixed the UI of the bank, although the interactions for it are still malfunctioning):
- To compensate for the lack of ‘ShowHideUI.cs’ (which is still on the Quest UI, but I won’t delete that… it seems to be doing its job there just fine. It just needs a little bit of cleaning up), I created a brand new script, called ‘ThirdPersonShowHideUI.cs’, which looks as follows:
using GameDevTV.UI.Inventories;
using UnityEngine;
public class ThirdPersonShowHideUI : MonoBehaviour
{
public GameObject UIContainer = null; // player Inventory
public GameObject otherInventoryContainer = null; // player bank
public InventoryUI otherInventoryUI = null; // the UI of the player bank
public bool HasOtherInventory => otherInventoryContainer != null;
void Start()
{
// when the game starts, deactivate the inventory, and the bank, if the bank exists:
UIContainer.SetActive(false);
if (otherInventoryContainer != null) otherInventoryContainer.SetActive(false);
}
public void ShowOtherInventory(GameObject go)
{
// Displaying the bank, when this function is called (mainly through a 'System.Action Callback', in 'OtherInventory.cs'):
UIContainer.SetActive(true);
otherInventoryContainer.SetActive(true);
otherInventoryUI.Setup(go);
}
}
I placed this on the bank, and then filled up the slots as follows:
next, I made some significant changes in ‘OtherInventory.cs’, so now it looks like this:
using System.Linq;
using RPG.Bank;
using RPG.Core;
using RPG.States.Player;
using UnityEngine;
namespace GameDevTV.Inventories {
[RequireComponent(typeof(Inventory))]
public class OtherInventory : MonoBehaviour, ITarget//, IRaycastable
{
private ThirdPersonShowHideUI thirdPersonShowHideUI;
private void Awake() {
thirdPersonShowHideUI = FindObjectsOfType<ThirdPersonShowHideUI>().FirstOrDefault(thirdPersonInventory => thirdPersonInventory.HasOtherInventory);
}
public void OpenBank(PlayerStateMachine player)
{
player.GetComponent<BankAction>().StartBankAction(transform, () => {thirdPersonShowHideUI.ShowOtherInventory(gameObject);});
}
public event System.Action OtherInventoryClosed;
public void CloseOtherInventory()
{
OtherInventoryClosed?.Invoke();
}
public bool IsValid()
{
return Vector3.Distance(GameObject.FindWithTag("Player").transform.position, transform.position) < 4.0f;
}
}
}
(NOTE: OpenBank is the function that I call from the ‘PlayerBankingState.cs’ script, so we can open up the Bank of the Player)
and finally, in ‘BankAction.cs’, I changed the ‘Update’ method, from this (the old one, for Point-and-Click):
/* public void Update() {
if (!target) return;
if (Vector3.Distance(transform.position, target.position) > acceptanceRadius) {
GetComponent<Mover>().MoveTo(target.position, 1);
}
else {
callback?.Invoke();
target = null;
GetComponent<Mover>().Cancel();
}
} */
to an extremely simple one, as follows:
void Update()
{
if (!target) return; else {callback?.Invoke(); target = null;}
}
If I’m not mistaken though, I think you’ll only need an ‘OtherInventory.cs’ script on your Banker though, and everything should hopefully work just fine from there onwards
[PROBLEM] I do not fully understand though, why in the world is it when I delete ‘target = null;’, there are significant performance issues, but when I keep it, it becomes stable? What does ‘target = null;’ do?! I thought this was only for targeting the banker when the game was point-and-click, WHAT DOES THIS HAVE TO DO WITH PERFORMANCE? (Not yelling, just going nuts on what this thing is doing…)
As for the Quit Button of the bank (and I am EXTREMELY SUSPICIOUS OF THIS APPROACH, PLEASE REVIEW FOR ME AND UPDATE ME IF IT WORKS OR NOT), Here’s the function I created for the ‘X’ button, in ‘OtherInventory.cs’:
public void CloseBank(PlayerStateMachine player)
{
ThirdPersonShowHideUI.CloseAllWindows();
player.SwitchState(player.Targeter.CurrentTarget ? new PlayerTargetingState(player) : new PlayerFreeLookState(player)); // go back to FreeLook, unless if you were under attack
}
and attached this function to the ‘X’ button
To compensate for the fact that somehow ‘OnOtherInventoryClosed’ never gets called, I just copied whatever I had in ‘SetLocomotionState’, threw it in the function, got it to work, and called it a day
The next comment has further instructions on how I got the first line of ‘CloseBank’ to work