Merging the Third Person Controller Course with the RPG Course

[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)

  1. 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;
    }
  1. 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):

  1. 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

[Further Instructions on the Bank Functions]

A. in ‘PlayerBankingState.cs’, I made a few changes in ‘Exit()’:

    public override void Exit()
    {
        Debug.Log("Player Exited Banking State");
        target.CloseBank(stateMachine);
        target.OtherInventoryClosed -= OnOtherInventoryClosed;
    }

B. In ‘OtherInventory.cs’, I made the following changes:

        public void CloseBank(PlayerStateMachine player) 
        {
            player.GetComponent<BankAction>().Cancel();
        }

C. in ‘BankAction.cs’, I changed the ‘Cancel()’ function a bit:

    public void Cancel() 
    {
        target = null;
        ThirdPersonShowHideUI.CloseAllWindows();
    }

D. in ‘ThirdPersonShowHideUI.cs’, I added this function:

    public static void CloseAllWindows() 
    {
        foreach (ThirdPersonShowHideUI tpShowHideUI in FindObjectsOfType<ThirdPersonShowHideUI>()) 
        {
            tpShowHideUI.UIContainer.SetActive(false);
            if (tpShowHideUI.otherInventoryUI != null) 
            {
                tpShowHideUI.otherInventoryContainer.SetActive(false);
            }
        }
    }

[PROBLEMS]

  1. Something to do with the InputReader.cs, I believe…:
MissingComponentException while executing 'performed' callbacks of 'UI/Bank[/Keyboard/x]'
UnityEngine.InputSystem.LowLevel.NativeInputRuntime/<>c__DisplayClass7_0:<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType,UnityEngineInternal.Input.NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType,intptr)
  1. Another one, this one has something to do with ‘Mover.cs’ trying to access the NavMeshAgent I believe…:
MissingComponentException: There is no 'NavMeshAgent' attached to the "Player" game object, but a script is trying to access it.
You probably need to add a NavMeshAgent to the game object "Player". Or your script needs to check if the component is attached before using it.
RPG.Movement.Mover.Cancel () (at Assets/Project Backup/Scripts/Movement/Mover.cs:115)
RPG.ResourceManager.ResourceGatherer.Cancel () (at Assets/Project Backup/Scripts/ResourceManager/ResourceGatherer.cs:208)
RPG.Core.ActionSchedular.StartAction (RPG.Core.IAction action) (at Assets/Project Backup/Scripts/Core/ActionSchedular.cs:32)
RPG.Bank.BankAction.StartBankAction (UnityEngine.Transform bankTarget, System.Action callback) (at Assets/Project Backup/Scripts/Bank/BankAction.cs:30)
GameDevTV.Inventories.OtherInventory.OpenBank (RPG.States.Player.PlayerStateMachine player) (at Assets/GameDev.tv Assets/Scripts/Inventories/OtherInventory.cs:20)
PlayerBankingState.Enter () (at Assets/Project Backup/Scripts/State Machines/Player/PlayerBankingState.cs:18)
RPG.States.StateMachine.SwitchState (RPG.States.State newState) (at Assets/Project Backup/Scripts/State Machines/StateMachine.cs:13)
RPG.States.Player.PlayerFreeLookState.InputReader_HandleBankingEvent () (at Assets/Project Backup/Scripts/State Machines/Player/PlayerFreeLookState.cs:198)
RPG.InputReading.InputReader.OnBank (UnityEngine.InputSystem.InputAction+CallbackContext context) (at Assets/Project Backup/Scripts/Input Controls/InputReader.cs:197)
UnityEngine.InputSystem.Utilities.DelegateHelpers.InvokeCallbacksSafe[TValue] (UnityEngine.InputSystem.Utilities.CallbackArray`1[System.Action`1[TValue]]& callbacks, TValue argument, System.String callbackName, System.Object context) (at Library/PackageCache/com.unity.inputsystem@1.5.1/InputSystem/Utilities/DelegateHelpers.cs:46)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)

[IGNORE THIS ONE, IT DOESN’T HAPPEN THIS OFTEN ANYMORE]

and 3. When I use my Construction System, having this line in ‘PlayerFreeLookState.InputReader_HandleBankingEvent’ means I cannot properly exit my construction and re-activate my ‘PlayerStateMachine’. In other words, my player does not safely land from the other controller… What does this line have to do with anything?:

        private void InputReader_HandleBankingEvent()
        {
            stateMachine.SwitchState(new PlayerBankingState(stateMachine, stateMachine.BankFinder.GetNearestBank()));
        }

I don’t know why the last one no longer happens, but I could’ve sworn that it used to happen…


[THE MOST IMPORTANT PROBLEM OF ALL]

AND THE BIGGEST PROBLEM OF ALL: THE LONGER YOU USE THE BANK, THE SLOWER IT GETS… How do we optimize and speed up this process further, and more importantly, how do we delete any unwanted data once the bank is done and dusted, to free up space for future data that’ll need it? It’s a serious pain to deal with :sweat_smile: (any chance we can minimize the number of items being dealt with in ‘InventoryUI.Redraw’? Wouldn’t that help it out a bit further? I know we don’t need to destroy and re-instantiate each slot, so… how do we only do that for the slots being changed?)

There is a thread on here that covers the lag issue. One of our fellow students did an indepth analysis. I am at work, so I can’t look it up. You should be able to find it. It is worth the effort.

1 Like

Good day Ed, thanks. we’re not talking about the one I asked for a while ago, for transferring entire inventories by chance, are we? Is it this one?

No, not one of your topics. It was another poster. I don’t remember who.

Plays “Man on a Mission - Oh the Larceny”, as he goes to hunt that post down

Alright I’ll go try hunt it down

Sir Brian, if this comment is still here, I still need help :smiley:

Edit 1: Haven’t found the thread, but I found this - still need the optimization solution though

been searching for the last hour like a madman, I can’t find that thread… -_*

1 Like

[Inventory Redraw() Framerate hiccups with high slot count](Inventory Redraw() Framerate hiccups with high slot count]
Here is one. This one is for inventory lag.

Here is one that is for shops but has a lot of good stuff.

been searching for the last hour like a madman, I can’t find that thread… -_*
[/quote]

Try adding a little sanity. It helps. :joy:

NAH, I’m either a sane person, or I finish the game :stuck_out_tongue:

COME ON, WE’VE BEEN THROUGH HELL AND BACK WITH THIS ONE, xD

This project broke me countless times, I almost gave up like a thousand times so far, and then Brian comes up with a solution and I’m back to the next bone-breaking issue… Brian, please, bank optimization whenever you feel better and it’s possible… You are our saviour :smiley:

Anyway, here is where I suspect where the real problem is, in ‘InventoryUI.cs’:

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);
            }
        }

I can’t properly think of a solution that would limit what gets destroyed and re-instantiated, but I know for a fact that I don’t need to destroy and re-instantiate EVERYTHING just to refresh the UI of a sender slot, and a receiver slot… that’s just a HUGE waste of resources that simply needs to get eliminated (and I can’t think of a solution as to how… :sweat_smile:)

In the meanwhile I shall go read Brian’s solution on that question @edc237 mentioned, MAYBE I can find something useful there

That is exactly what the first topic I linked above covers.

1 Like

I’m reading it through, believe me… I’m just seeing what can be extracted and placed into our script, since that topic is dedicated to solving the RowUI issue for shops… my issue is the UI for the inventory

Anyway, I’ll go grab something to eat for the time being (it’s 7PM, didn’t eat anything today), and then return to solve this issue

Look at the one above it. It is specifically about inventory.

1 Like

OK I’m a little confused… where? Who? @edc237 (AHH, NEVERMIND… SILLY ME… I HAVE COMPLETELY MISSED THAT COMMENT!)

(I’ll also go implement that solution tbh, that sounds like a solution to a nightmare waiting to happen)

OK so… 3 things to do:

  1. Fix the whole ‘X’ button working from anywhere and deactivating the player, when it’s not supposed to work unless he’s near the bank (Ahh… the dumb things that happen when you forget your ‘if’ statements)
  2. Wait for Brian’s solution for the bank UI
  3. Go through the article and fix the same issue that post writer has

This is the one that covers inventory.

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 :confused:)

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

1 Like

You said you would back up the project, so it will not be beyond repair. Unfortunately, you have added so many extra things that a solution for the lag based on the standard project will require a lot of extra work. You have all of tools in front of you. Take a break, go for a walk, read a book. Do something else for an hour or two and then come back to it. Your subconscious mind works better on problems like this if you conscious mind is distracted.

I wrote that almost a day ago, Ed… Obviously I took an hour break (I just came back 30 minutes ago), and obviously I have a backup of my work :smiley: (it takes 25 minutes to make one, not 25 hours :stuck_out_tongue:)

Well that’s what living on opposite sides of the globe will do :laughing:

1 Like

wait till you see the new magic effect I discovered trying to get this algorithm to work… Inventory sizes are now getting multiplied the more I touch them

Totally nothing suspicious going on here :smiley:

kinda disagree with this one tbh… What makes a simple algorithm work, and a slightly more complex version fail? I’m 99% sure something new is responsible for this problem, but I’m struggling to wrap my head around what’s going on in that algorithm, so I don’t know how to fix it (yet)

Edit 1: OK I don’t think I see where the problem is… The half before the final ‘foreach’ loop of the new algorithm pretty much never gets called after you pickup the first item

Edit 2: Looks like it’ll only go to the first if statement when you’re picking your first item up, but most of the time it’ll just skip to the foreach loop at the bottom of the function (and the number of logs coming out of this are quite large, 100 calls, and that’s exactly 2x the size of my Player’s Inventory)… Something fishy is going on

Edit 3: Tested the system as-is outside of the engine, don’t think I need performance optimization measures tbh… I’ll just fully test the game as-is for now

Edit 4: No Shop Optimization issues either (now I remember I solved this with Brian before), just a “Shop won’t open for some reason after a bit of gameplay, unless you “Save and Quit” and return to the game” issue (haven’t solved this one with Brian yet)

Privacy & Terms