Page 1 of 1

Custom Savers Enemy Variables

Posted: Fri Apr 05, 2024 9:33 am
by MeyOrMeyNot
Hi,
I recently started working on a turn based combat game and I want to save certain ints and bools of the enemy, I wrote a custom saver but it doesn't seem to be working. In the Battle Scene the Health and bool isDead gets set correctly in the EnemyController script but when I Load the Overworld scene the Enemy stats have reset. Am I missing something? Also this script and the EnemyController are on the Enemy GameObject.( I apply a DontDestroyOnLoad method with on Trigger so I take the enemy into the Battle Scene and change the health etc. Its probably not the smartest way but it works so far)

Code: Select all

using System;
using UnityEngine;
using PixelCrushers;
[RequireComponent(typeof(EnemyController))]
public class EnemyStatsSaver : Saver
{
    [Serializable]
    public class Data
    {
        public int health;
        public bool isDead;
    }
    public override string RecordData()
    {
        var enemyController = GetComponent<EnemyController>();
        var data = new Data();
        data.health = enemyController.currentHealth;
        data.isDead = enemyController.isDead;
        return SaveSystem.Serialize(data);
    }
    
    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return; // If we didn't receive any save data, exit immediately.
        var data = SaveSystem.Deserialize<Data>(s);
        if (data == null) return; // If save data is invalid, exit immediately.
        var enemyController = GetComponent<EnemyController>();
        enemyController.currentHealth = data.health;
        enemyController.isDead = data.isDead;
    }
}

Re: Custom Savers Enemy Variables

Posted: Fri Apr 05, 2024 10:37 am
by Tony Li
Hi,

Add some Debug.Log() lines to your RecordData() and ApplyData() methods, or set breakpoints in your code editor, to make sure those methods are being called.

Change scenes using any of these techniques.

And make sure your EnemyStatsSaver component has a unique Key value.

Re: Custom Savers Enemy Variables

Posted: Wed Jul 10, 2024 5:00 pm
by MeyOrMeyNot
Hi,

sorry for the late reply that works perfectly.

But now I have another question about saving. I have an inventory and I want to save the Items inside on Save & Load.
I already made a Custom saver and the Debug from PlayerPrefsSavedGameDataStorer shows the right item ID number and slot but it doesnt show up in the Inventory properly. The amount gets depicted correctly but the Item isn't inside the Item Slot.

Code: Select all

public Inventory inventory;
    [System.Serializable]
    public struct InventorySlotRecord
    {
        public string itemID;
        public int number;
    }

    [System.Serializable]
    public class Data
    {
        public InventorySlotRecord[] slots;
    }

    public override string RecordData()
    {
        var data = new Data();
        inventory = FindObjectOfType<Inventory>();
        int size = inventory.inventorySize;
        var slotStrings = new InventorySlotRecord[size];
        data.slots = new InventorySlotRecord[size];
        var invSlots = inventory.slots;

        for (int i = 0; i < size; i++)
        {
            if (invSlots[i].item != null)
            {
                slotStrings[i].itemID = invSlots[i].item.GetItemID();
                slotStrings[i].number = invSlots[i].number;
            }
        }

        data.slots = slotStrings;
        Debug.Log("Record");
        return SaveSystem.Serialize(data);
    }

    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return; // No data to apply.
        Data data = SaveSystem.Deserialize<Data>(s);
        if (data == null) return; // Serialized string isn't valid.
        int size = data.slots.Length;
        var slotStrings = data.slots;
        inventory = FindObjectOfType<Inventory>();
        inventory.CreateNewInventory(size);

        for (int i = 0; i < size && i < ((ICollection)inventory.slots).Count; i++)
        {
            var slot = inventory.slots[i];
            if (slotStrings[i].itemID != null)  // Check itemID for null
            {
                slot.item = InventoryItem.GetFromID(slotStrings[i].itemID);
                slot.number = slotStrings[i].number;
                inventory.slots[i] = slot;
            }
        }
        inventory.UpdateInventory();
        Debug.Log("Apply");
    }

And these are Inside my Inventory script:

Code: Select all

public void UpdateInventory()
        {
            if (inventoryUpdated != null)
            {
                inventoryUpdated();
            }
        }
        public void CreateNewInventory(int size)
        {
            inventorySize = size;
            slots = new InventorySlot[inventorySize];
        }

Re: Custom Savers Enemy Variables

Posted: Wed Jul 10, 2024 7:46 pm
by Tony Li
I recommend either stepping through both methods (RecordData and ApplyData) with your code debugger or adding Debug.Log lines to print out what it's saving and restoring, and which items InventoryItem.GetFromID() is finding.

Re: Custom Savers Enemy Variables

Posted: Thu Jul 11, 2024 2:58 am
by MeyOrMeyNot
I added the debugs and checked and the Items get saved correctly and restored correctly as well as far as I can tell. I checked the ItemIDs and they are also the correct ones.But still the Inventory slots stay empty.
However from the Debugs:

Code: Select all

Debug.Log(InventoryItem.GetFromID(slotStrings[i].itemID));
Debug.Log(InventoryItem.GetFromID(slotStrings[0].itemID));
I get Null in the inspector.
Saving slot 0: ItemID = 9daef173-d800-40a9-974a-92aca2e04c02, Number = 3
Restoring slot 0: ItemID = 9daef173-d800-40a9-974a-92aca2e04c02, Number = 3

I added some more Debugs in the GetItemID in the InventoryItem script:

Code: Select all

public static InventoryItem GetFromID(string itemID)
        {
            Debug.Log($"GetFromID called with itemID: {itemID}");

            if (itemLookupCache == null)
            {
                itemLookupCache = new Dictionary<string, InventoryItem>();
                var itemList = Resources.LoadAll<InventoryItem>("");
                foreach (var item in itemList)
                {
                    if (itemLookupCache.ContainsKey(item.itemID))
                    {
                        continue;
                    }

                    itemLookupCache[item.itemID] = item;
                }
            }

            if (itemID == null || !itemLookupCache.ContainsKey(itemID))
            {
                Debug.Log($"ItemID: {itemID} not found in itemLookupCache.");
                return null;
            }

            Debug.Log($"ItemID: {itemID} found in itemLookupCache.");
            return itemLookupCache[itemID];
        }
In the first Debug the IDs are still correct but when it searches the itemLookupCache it says it can't find it.

Re: Custom Savers Enemy Variables

Posted: Thu Jul 11, 2024 3:33 am
by MeyOrMeyNot
Ok I got it wokring by putting the items (which are scriptable objects) into the Resources folder & so far it seems to work without a problem
Thanks for the fast help! :D

Re: Custom Savers Enemy Variables

Posted: Thu Jul 11, 2024 8:54 am
by Tony Li
Great! I'm glad it's working now.