How to serialize SerializableMap and save to game state
Hi,
I developed my own Inventory/Shop/Purchase system, but I have trouble serializing a dictionary ( I made use of the SerializableMap in Naninovel)
I have a customized ScritableObject class Item with below code:
Code: Select all
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item", order = 0)]
[Serializable]
public class Item : ScriptableObject
{
public string itemName;
public Sprite itemImage;
[TextArea]
public string itemInfo;
public bool gift;
public int price;
}
In my InventoryManager, I implement the SerializableMap as below
Code: Select all
[Serializable]
public class InventoryMap: SerializableMap<Item, int>
{
public InventoryMap(){}
public InventoryMap(InventoryMap map){}
}
And I did similar job in InventoryManager as in https://naninovel.com/guide/state-manag ... stom-state
Code: Select all
[Serializable]
public class GameState
{
public InventoryMap SaveItemDict;
}
public static InventoryMap itemDict;
void Awake()
{
if (instance != null)
{
Destroy(this);
Debug.Log("singleton destroy...");
}
instance = this;
itemDict = new InventoryMap();
stateManager = Engine.GetService<IStateManager>();
}
private void OnEnable() {
stateManager.AddOnGameSerializeTask(SerializeState);
stateManager.AddOnGameDeserializeTask(DeserializeState);
}
private void OnDisable()
{
stateManager.RemoveOnGameSerializeTask(SerializeState);
stateManager.RemoveOnGameDeserializeTask(DeserializeState);
}
private void SerializeState (GameStateMap stateMap)
{
var state = new GameState()
{
SaveItemDict = itemDict // I would suspect is there a copy issue/not just simple equal here
};
stateMap.SetState(state);
}
private UniTask DeserializeState(GameStateMap stateMap)
{
var state = stateMap.GetState<GameState>();
if (state is null) return UniTask.CompletedTask;
itemDict = state.SaveItemDict; // I would suspect is there a copy issue/not just simple equal here
return UniTask.CompletedTask;
}
The issue could be described as below:
- If I add an <Item, int> ( an item, number of Item added) to the bag, and save, it was working fine. I exit play mode in unity editor, restart the game, its working fine as well.
- The problem happens when I exit the whole unity editor, when I restart the Unity Editor, it always gives an ArgumentNullException
ArgumentNullException: Value cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <695d1cc93cca45069c528c15c9fdd749>:0)
2[TKey,TValue].set_Item (TKey key, TValue value) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Collections.Generic.Dictionary
Naninovel.SerializableMap2[TKey,TValue].OnAfterDeserialize () (at Assets/Naninovel/Runtime/Common/Collections/SerializableMap.cs:67)
1:Run() (at Assets/Naninovel/ThirdParty/UniTask/UniRx.Async/CompilerServices/MoveNextRunner.cs:18)
UnityEngine.JsonUtility:FromJson(String, Type)
Naninovel.StateMap:OnAfterDeserialize() (at Assets/Naninovel/Runtime/State/StateMap.cs:33)
Naninovel.GameStateMap:OnAfterDeserialize() (at Assets/Naninovel/Runtime/State/GameStateMap.cs:59)
UnityEngine.JsonUtility:FromJson(String)
Naninovel.<DeserializeDataAsync>d__20:MoveNext() (at Assets/Naninovel/Runtime/Common/SaveSlotManager/IOSaveSlotManager.cs:157)
UniRx.Async.CompilerServices.MoveNextRunner
UniRx.Async.UniTaskCompletionSource1:TryInvokeContinuation() (at Assets/Naninovel/ThirdParty/UniTask/UniRx.Async/UniTaskCompletionSource.cs:344)
1:TrySetResult(String) (at Assets/Naninovel/ThirdParty/UniTask/UniRx.Async/UniTaskCompletionSource.cs:363)
UniRx.Async.UniTaskCompletionSource
UniRx.Async.CompilerServices.AsyncUniTaskMethodBuilder1:SetResult(String) (at Assets/Naninovel/ThirdParty/UniTask/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs:227)
1:Run() (at Assets/Naninovel/ThirdParty/UniTask/UniRx.Async/CompilerServices/MoveNextRunner.cs:18)
Naninovel.<UnzipStringAsync>d__28:MoveNext() (at Assets/Naninovel/Runtime/Common/Utilities/StringUtils.cs:395)
UniRx.Async.CompilerServices.MoveNextRunner
UnityEngine.UnitySynchronizationContext:ExecuteTasks() (at /Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/UnitySynchronizationContext.cs:107)
I tried debugging, I could see in StateMap, ObjectMap, the dictionary is loaded fine. After this step, it jumps into the ArgumentNullException, I could not figure out what is happening next and I suspected the way I use the SerializableMap to serialize the dictionary might be wrong (since it contains my custom class)
Could you provide any hint on this? Really appreciate your help.
Thanks!