Migrating Level Manager to Dialogue System

Announcements, support questions, and discussion for the Dialogue System.
Mackerel_Sky
Posts: 111
Joined: Mon Apr 08, 2019 8:01 am

Re: Migrating Level Manager to Dialogue System

Post by Mackerel_Sky »

Hi Tony,

Apologies for getting back to you so late. I gave the manual another read and I understand what it does now. To extend the saving functionality to capture my player data, I wrote another custom saver to . I am just running into a bit of difficulty in getting the reference of scriptable objects I use for my player inventory to apply properly even though it seems to be deserializing correctly. My code is as follows:

Code: Select all

        public override void Start()
        {
            inventory = GetComponent<PlayerInventory>();
            gunInventory = GetComponentInChildren<GunController>();
            playerStatus = GetComponent<PlayerStatus>();
            playerHealth = GetComponent<PlayerHealthController>();
            saveData = new PlayerSaveData();
            saveData.inventory = new InventoryObjectTemplate[inventory.inventoryList.Length];
            saveData.storyInventory = new InventoryObjectTemplate[storyInventory.itemList.Length];

        }
        public override void ApplyData(string data)
        {
            if (string.IsNullOrEmpty(data))
            {
                //Debug.Log("no save detected, implementing original data");
            }
            else
            {
                print("applying player data");
                PlayerSaveData saveData= SaveSystem.Deserialize<PlayerSaveData>(data);
                print(data);
                inventory.inventoryList = saveData.inventory;
                storyInventory.itemList = saveData.storyInventory;
                gunInventory.guns = saveData.gunsInventory;
                gunStorage.storedGuns = saveData.gunStorage;
                playerHealth.health = saveData.health;
                playerHealth.defaultMaxHealth = saveData.maxHealth;
                playerStatus.hunger = saveData.hunger;
                playerStatus.hPText.text = saveData.health.ToString();
                playerStatus.hungerText.text = saveData.hunger.ToString();
                }
              }
              
                      public override string RecordData()
        {
            if (SaveSystem.instance != null)
            {
                saveData.inventory = inventory.inventoryList;
                saveData.storyInventory = storyInventory.itemList;
                saveData.gunsInventory = gunInventory.guns;
                saveData.gunStorage = gunStorage.storedGuns;
                saveData.health = playerHealth.health;
                saveData.maxHealth = playerHealth.defaultMaxHealth;
                saveData.hunger = playerStatus.hunger;
            }
            return SaveSystem.Serialize(saveData);
        }
   
               
The player save data class is a serializable class like the loot chest data we walked through earlier.

Code: Select all

	[System.Serializable]
    public class PlayerSaveData
    {
        public InventoryObjectTemplate[] inventory;
        public InventoryObjectTemplate[] storyInventory;
        public GunTemplate[] gunsInventory;
        public GunTemplate[] gunStorage;

        public int hunger;
        public int health;
        public int maxHealth;
    }
I can see the inventories getting printed when ApplyData is being called but I am not sure why they are not copying over when this approach works for the LootChest controller. What's weirder is that the gun inventory and storage seem to be copying over fine.

I'm sure this is not a Dialogue System error but figured I'd just post it here while i figure out what is going on. If you think you know what is going on please feel free to let me know.
User avatar
Tony Li
Posts: 22051
Joined: Thu Jul 18, 2013 1:27 pm

Re: Migrating Level Manager to Dialogue System

Post by Tony Li »

Hi,

What is InventoryObjectTemplate? Is it a ScriptableObject? Or is it something that's serializable?
Mackerel_Sky
Posts: 111
Joined: Mon Apr 08, 2019 8:01 am

Re: Migrating Level Manager to Dialogue System

Post by Mackerel_Sky »

Hey Tony,

InventoryObjectTemplate is a scriptable object. I did a quick google and looks like ScriptableObjects are not serializable without jumping through a lot of hoops. I'll do some more reading on the topic and see if I can find a way around it. Off the top of my head I think I could grab the item's position, ID and stack from the scriptable object, serialize that, and generate a new scriptable object based on the data when I load.

Thanks for the pointer.
User avatar
Tony Li
Posts: 22051
Joined: Thu Jul 18, 2013 1:27 pm

Re: Migrating Level Manager to Dialogue System

Post by Tony Li »

If the inventory and storyInventory arrays point to ScriptableObject asset files, you can record the name of each asset in RecordData. In ApplyData, somehow point the array back to the actual asset -- for example, putting them in a Resources folder and using Resources.Load<InventoryObjectTemplate>(name).

Or you can make another ScriptableObject asset type that contains a list of references to InventoryObjectTemplate assets. In this case, in RecordData record each inventory/storyInventory element's index in the list asset. In ApplyData, look up each element by the index in the list asset.

However, if you're allocating inventory/storyInventory's ScriptableObject elements in memory at runtime, you'll have to do something like what you suggest above.
Mackerel_Sky
Posts: 111
Joined: Mon Apr 08, 2019 8:01 am

Re: Migrating Level Manager to Dialogue System

Post by Mackerel_Sky »

Hey Tony,

Thanks for the help. I've almost managed to get everything up and running as I want it. I think there's just one more problem with the custom saver I've set up with the player. It seems to be saving and applying data whenever I move to a new scene, even without any input from me. I have checked that all the boxes in the Saver are unticked so I don't think it should be doing anything unless I specifically tell it to. Do you have any idea what is happening?

Thanks,
User avatar
Tony Li
Posts: 22051
Joined: Thu Jul 18, 2013 1:27 pm

Re: Migrating Level Manager to Dialogue System

Post by Tony Li »

Hi,

That's probably by design. When you change scenes using SaveSystem.LoadScene, or a ScenePortal component, or LoadLevel() sequencer command, it tells the savers in the original scene to save their states to the Save System's memory. After loading the new scene, the Save System tells the savers in the new scene to check if they have any saved state in the Save System's memory and use it.
Mackerel_Sky
Posts: 111
Joined: Mon Apr 08, 2019 8:01 am

Re: Migrating Level Manager to Dialogue System

Post by Mackerel_Sky »

Hi Tony,

Thanks for the reminder- I remember it now from the first time we talked about transitioning over to the save system. I might be able to get around it relatively easily by only enabling the custom saver when the player accesses a save point.
User avatar
Tony Li
Posts: 22051
Joined: Thu Jul 18, 2013 1:27 pm

Re: Migrating Level Manager to Dialogue System

Post by Tony Li »

Hi,

Is there a reason why you don't want to persist the data across scene changes?
Mackerel_Sky
Posts: 111
Joined: Mon Apr 08, 2019 8:01 am

Re: Migrating Level Manager to Dialogue System

Post by Mackerel_Sky »

This particular saver handles the player's inventory, weapons, health and other stats - I was only intending to use it as part of the slot save/save point system that would be used when the player is quitting or loading the game. As the player is a don't destroy on load object, there isn't any need to save these states across scenes. Also, I think it would lead to very weird scenarios where for example, the player would receive damage, have their health autosaved, go to another scene to heal, but then come back and have their damaged state applied.
User avatar
Tony Li
Posts: 22051
Joined: Thu Jul 18, 2013 1:27 pm

Re: Migrating Level Manager to Dialogue System

Post by Tony Li »

But each time you change scenes, the saver will save its data, even for persistent objects. So when you go to a scene and heal and come back, the health should be the healed version.

Anyway, to prevent it from saving when changing scenes, add this code to your saver:

Code: Select all

public bool isChangingScenes = false;

public override void OnBeforeSceneChange()
{
    isChangingScenes = true;
}

public override string RecordData()
{
    if (isChangingScenes) return SaveSystem.currentSavedGameData.GetData(key); // Don't bother recording new data.
    // (the rest of your RecordData method here)
}

public override void ApplyData(string s)
{
    if (isChangingScenes)
    { // Don't bother applying data; we're just changing scenes.
        isChangingScenes = false;
        return;        
    }
    // (the rest of your ApplyData method here)
}
Post Reply