Equipment Slots Not Saving between scenes

Most everything is functioning correctly at this point. I can pick up an Item, it shows up in my inventory, I can equip it, it equips correctly, and everything is fine until i try to enter a new scene. If I dont have the item equipped it saves fine and stays in my inventory, but If I have the Item equipped, or If I have the inventory canvas open, when I enter a portal. The inventory has disappeared, and the weapon is no longer equipped…

The first thing that comes to mind is to make sure that the player in each scene has the same ID in the SaveableEntity, preferably “player”

Are there any error messages in the console when you transition to the new scene?

Unfortunately, no… I have figured out through debugging various points with print statements, that the Equipment.cs ISaveable Implementation is not being called upon scene transition… but I cant figure out why.
Neither ISaveable.CaptureState(object state), or ISaveable.RestoreState(object state), are getting called… but everything else is. So, I am going back to an earlier commit to try again… I’ve run into issues with the saving system and checkpoint saving through the portals, the entire project, but I have so far been able to figure out where I went wrong, so it doesn’t surprise me that I am yet again…

Are your inventory items in a folder named Resources?

Yes, but the weapons, and the wearables are in 2 separate folders named Resources… I hadn’t thought of that. But, they save when just in the inventory, I can go to a new scene with the item in my inventory, equip it, use it, and put it back in my inventory, go to a new scene, and it is still there… and I can reequip it, use it… and so on. But, if its equipped… its gone. I will consolidate the resource folders though, and see if that fixes it.

Odd that Equipment wouldn’t work when Inventory is working. Is the equipment back when you return to the first scene?

No, it was completely gone, as if when the scene updated the player before fading in, it just didn’t save the equipment, so it loaded an empty state for the equipment. I went back to a previous commit, right before I imported the Inventory assets, and I have rebuilt up to the point that I have the Test Helmet pick up, working, and saving in both inventory, and equipment… I have not re-implement the weapons or Fighter script changes, hopefully things will continue to work after that. I will tackle those again, in the morning.

Oh, one more thing to check… make sure you have one and only one Equipment on the player. This applies to all scenes

I have changed the weapon config from a Scriptable Object to a Equipable Item and this particular change now causes the following error… “ArgumentNullException: Value cannot be null. Parameter Name: Key” This error now occurs whenever I transition from scene to scene, whether I have anything in my inventory or not… preventing the player from updating on scene transition… hmm.

Here is my Weapon Config…

using RPG.Attributes;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RPG.Combat
{
    [CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Make New Weapon", order = 0)]

    public class WeaponConfig : EquipableItem
    {
        public Weapon WeaponPrefab;
        public AnimatorOverrideController AnimatorOverride;
        public float WeaponBonus;
        public float percentageBonus = 0;
        public float WeaponRange;
        public float AttackTime;
        public bool isRightHanded = true;
        public Projectile Projectile = null;

        const string weaponName = "Weapon";

        public void Spawn(Transform rightHand, Transform leftHand, Animator animator)
        {
            DestroyOldWeapon(rightHand, leftHand);

            if(WeaponPrefab != null)
            {
                Transform handTransform = GetHandTranform(rightHand, leftHand);

               Weapon weapon = Instantiate(WeaponPrefab, handTransform);
                weapon.gameObject.name = weaponName;


            }

            var overrideController = animator.runtimeAnimatorController as AnimatorOverrideController;

            if (AnimatorOverride != null)
            {
                animator.runtimeAnimatorController = AnimatorOverride;
            }

            else if (overrideController != null)
            {
                animator.runtimeAnimatorController = overrideController.runtimeAnimatorController;

            }
        }

        private void DestroyOldWeapon(Transform rightHand, Transform leftHand)
        {

            Transform oldWeapon = rightHand.Find(weaponName);
            if(oldWeapon == null) 
            { 

                oldWeapon = leftHand.Find(weaponName);

            }
            if(oldWeapon == null)
            { 
                return; 
            }

            oldWeapon.name = "DESTROYING";
            oldWeapon.gameObject.SetActive(false);

            Destroy(GameObject.Find("DESTROYING"));
        }

        private Transform GetHandTranform(Transform rightHand, Transform leftHand)
        {
            Transform handTransform;
            if (isRightHanded)
            { handTransform = rightHand; }
            else
            { handTransform = leftHand; }

            return handTransform;
        }

        public void LaunchProjectile(Transform rightHand, Transform leftHand, Health _target, GameObject _instigator, float calculatedDamage)
        {
            Projectile projectileInstance = Instantiate(Projectile, GetHandTranform(rightHand, leftHand).position, Quaternion.identity);
            projectileInstance.SetTarget(_target, _instigator,calculatedDamage);
        }
        public bool HasProjectile()
        { 
            return Projectile != null; 

        }



    }
}

It’s likely that the ID hasn’t been initialized yet in the WeaponConfig. When you convert, it doesn’t always automagically fix these things.

Try selecting each WeaponConfig one at a time in the Editor so that the Inspector shows up. A unique identifier should automagically appear in the ID field.

No, unfortunately… all of them have unique ItemId’s… the break is happening within RestoreState(object state) of the Equipment.cs script…

 object ISaveable.CaptureState()
        {
            print($"Equipment Saving");
            var equippedItemsForSerialization = new Dictionary<EquipLocation, string>();
            foreach (var pair in equippedItems)
            {
                equippedItemsForSerialization[pair.Key] = pair.Value.GetItemID();
            }
            return equippedItemsForSerialization;
        }

        void ISaveable.RestoreState(object state)
        {
            print($"Equipment Loading");
            equippedItems = new Dictionary<EquipLocation, EquipableItem>();

            var equippedItemsForSerialization = (Dictionary<EquipLocation, string>)state;

            foreach (var pair in equippedItemsForSerialization) // <= break is here, within this loop.
            {

                var item = (EquipableItem)InventoryItem.GetFromID(pair.Value);
                print($"{item}");
                if (item != null)
                {
                    equippedItems[pair.Key] = item;//
                }
            }
        }
    }

I tried a different approach, to put the weapon config in a script that Inherited from EquipableItem, but I ran into a serialization error on the scriptable object, so I tried with a GameObject prefab, and have any references needed for the weaponConfig, go through that prefab’s public WeaponConfig getter, and I though that since GameObjects were serializable it would work… it looked promising, everything equipped, but I ran into the same Serialization error, this time on the GameObject (its in my resource folder), so alas… I’m lost.

This is the full error I get in the console…

ArgumentNullException: Value cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Collections.Generic.Dictionary`2[TKey,TValue].ContainsKey (TKey key) (at <695d1cc93cca45069c528c15c9fdd749>:0)
GameDevTV.Inventories.InventoryItem.GetFromID (System.String itemID) (at Assets/Asset Packs/GameDev.tv Assets/Scripts/Inventories/InventoryItem.cs:53)
GameDevTV.Inventories.Inventory.GameDevTV.Saving.ISaveable.RestoreState (System.Object state) (at Assets/Asset Packs/GameDev.tv Assets/Scripts/Inventories/Inventory.cs:248)
GameDevTV.Saving.SaveableEntity.RestoreState (System.Object state) (at Assets/---Game Files----/Scripts/Saving/SaveableEntity.cs:64)
GameDevTV.Saving.SavingSystem.RestoreState (System.Collections.Generic.Dictionary`2[TKey,TValue] state) (at Assets/---Game Files----/Scripts/Saving/SavingSystem.cs:104)
GameDevTV.Saving.SavingSystem+<LoadLastScene>d__0.MoveNext () (at Assets/---Game Files----/Scripts/Saving/SavingSystem.cs:34)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <07c89f7520694139991332d3cf930d48>:0)

Ohhh… Kay… So, I think I fixed it… so far it looks good, everything seems to be working correctly!!! Yay!!!
What I did was create an entirely new WeaponItem.cs, which inherits from EquipableItem. I then copied all of the logic from WeaponConfig.cs over to the new WeaponItem.cs, and renamed the references to the WeaponConfig, within Fighter.cs, to WeaponItem… Its the exact same script, just copied over, and with a different name but Ive gotten no errors yet, and Ive tested the saving system, the checkpoints, scenetransitions… phew… that was a pain in the ass… lol

The error itself was indicating that you were trying to retrieve an item based on a null string (hence my initial advice). Interestingly enough, you mentioned that they had itemIDs, but even if they didn’t, the way InventoryItems are setup once they are opened in the inspector, they are filled, so you wouldn’t actually know if they didn’t have ids.

It’s possible that the save file still had the null item ids saved.

1 Like

Well, thank you for the advice. It lead me down new paths of thinking, until I was able to come up with a solution so I appreciate the help. I have now tested all of the scenes I have in my build, I do have to convert the old Weapon Config stats to the new Weapon Items, so they have the same values, So I had to make the Sword, Fireball, Bow, and Unarmed Weapon Items, equivalents, but they are all working, saving in inventory, and equipment! So I am pleased. :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms