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