Custom Savers Enemy Variables

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
MeyOrMeyNot
Posts: 10
Joined: Mon May 16, 2022 5:49 am

Custom Savers Enemy Variables

Post 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;
    }
}
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Savers Enemy Variables

Post 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.
MeyOrMeyNot
Posts: 10
Joined: Mon May 16, 2022 5:49 am

Re: Custom Savers Enemy Variables

Post 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];
        }
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Savers Enemy Variables

Post 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.
MeyOrMeyNot
Posts: 10
Joined: Mon May 16, 2022 5:49 am

Re: Custom Savers Enemy Variables

Post 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.
MeyOrMeyNot
Posts: 10
Joined: Mon May 16, 2022 5:49 am

Re: Custom Savers Enemy Variables

Post 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
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Savers Enemy Variables

Post by Tony Li »

Great! I'm glad it's working now.
Post Reply