Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity序列化字典“索引超出范围”在12项之后_C#_Dictionary_Serialization_Unity3d_Deserialization - Fatal编程技术网

C# Unity序列化字典“索引超出范围”在12项之后

C# Unity序列化字典“索引超出范围”在12项之后,c#,dictionary,serialization,unity3d,deserialization,C#,Dictionary,Serialization,Unity3d,Deserialization,更新:这是Unity确认的错误,已存档 我已经为int:Object创建了一个通用的可序列化字典和一个特定的字典 using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEditor; /// <summary> /// Is what it sounds like /// </summary> [System.Serializable] publ

更新:这是Unity确认的错误,已存档

我已经为int:Object创建了一个通用的可序列化字典和一个特定的字典

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

/// <summary>
/// Is what it sounds like
/// </summary>
[System.Serializable]
public class SerializableDictionary<TKey,TValue> : Dictionary<TKey,TValue>, ISerializationCallbackReceiver 
{
  [SerializeField]
  protected List<TKey> keys = new List<TKey>();

  [SerializeField]
  protected List<TValue> values = new List<TValue>();

  //Save the dictionary to lists
  public void OnBeforeSerialize()
  {
    keys.Clear();
    values.Clear();
    foreach(KeyValuePair<TKey,TValue> pair in this)
    {
        keys.Add(pair.Key);
        values.Add(pair.Value);
    }
  }

  //Load the dictionary from lists
  public void OnAfterDeserialize()
  {
    this.Clear();

    if(keys.Count != values.Count)
    {
      throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable."));
    }

    for(int i = 0; i<keys.Count; i++)
    {
      this.Add(keys[i], values[i]);
    }
  }
}

[System.Serializable]
public class DictionaryOfStringAndInt : SerializableDictionary<string, int> { }

[System.Serializable]
public class DictionaryOfIntAndSerializableObject : SerializableDictionary<int, ScriptableObject> 
{
}
下面是代码,在解析CSV中的a行之后,我将一个M_Card实例放入字典:

public class M_Card : ScriptableObject

{

  public E_CardTypes cardTypeID;

  public int rankID;

  public int rarityID;

  public int qualityID;

  public int editionID;

  public Sprite sprite;

 public M_Card()
 {
    cardTypeID                  = 0;
    rankID                      = 0;
    qualityID                   = 0;
    sprite = null;
 }

}
 private void LoadActionCards()
 {
    List<Dictionary<string, object>> listData = CSVReader.Read("Actions");

    for (var i = 0; i < listData.Count; i++)
    {
      Dictionary<string, object> data = listData[i];

      string name = (string)data["Name"];
      M_ActionCard card = ScriptableObjectCreator.createActionCard(name);

      int cardTypeID  = (int)data["CardTypeID"];
      card.cardTypeID = (E_CardTypes)cardTypeID;

      AssignActionCardValues(card, data);

      Database.ACTION_CARD_LIST.Add(card);

      // THIS IS WHERE I MAP THE TYPEID TO THE M_CARD OBJECT
      // THIS IS WHERE THE OBJECT IS ADDED TO THE DICTIONARY
      Database.ACTION_CARD_MAP[card.ID] = card;
    }
  }
private void LoadActionCards()
{
List listData=CSVReader.Read(“操作”);
对于(var i=0;i
所以现在我有4个数据表(武器、头盔、盔甲、职业)。但是,如果这些表中有超过12项,我会在第13项中得到100%的错误。我仍在调查,但以下是如何将键添加到词典中

请注意,M_头盔卡与M_动作卡完全相同,它们都只是M_卡的空子类

这里有一些图片来补充一些证据。第一种是16顶头盔。出现错误

然后在这里我做了,所以只有12个,错误消失了。

任何超过12个错误的列表。实际的项目并不重要(因此它不像一个特定的第13个项目被损坏,13个相同的项目仍然会导致此错误)

此刻我非常困惑

(我想问题可能是我有一个
Sprite
类,该类正在序列化,数据太多,但当我去掉它时,问题仍然存在)

更新这里是一个指向存在此问题的示例项目的链接(所有不相关的内容都已删除)

要产生错误,请执行以下操作: 单击heirachy中的
数据库
对象,然后单击
更新数据库
按钮

然后点击play,您将看到错误

然后,如果您想查看第13项的效果,请打开头盔CSV文件(
\Assets\Resources\ExcelData
),然后删除第13项。然后再次更新数据库。然后点击播放。错误将会消失


这是一个重要的WTF:?

我偶然发现了同样的问题。看起来Unity的序列化有时会破坏序列化字典的内部结构,因此无法添加其他值

在我的例子中,我通过在
SerializableDictionary
上实现
IDictionary
接口并将其功能委托给一个私有
Dictionary
对象来消除这些错误,该对象不受Unity序列化的影响

这是我在VisualStudio的帮助下生成的解决方案

using UnityEngine;
using System.Collections.Generic;
using System.Collections;

[System.Serializable]
public class SerializableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField]
    private List<TKey> keys = new List<TKey>();

    [SerializeField]
    private List<TValue> values = new List<TValue>();

    private Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();

    public ICollection<TKey> Keys
    {
        get
        {
            return ((IDictionary<TKey, TValue>)dictionary).Keys;
        }
    }

    public ICollection<TValue> Values
    {
        get
        {
            return ((IDictionary<TKey, TValue>)dictionary).Values;
        }
    }

    public int Count
    {
        get
        {
            return ((IDictionary<TKey, TValue>)dictionary).Count;
        }
    }

    public bool IsReadOnly
    {
        get
        {
            return ((IDictionary<TKey, TValue>)dictionary).IsReadOnly;
        }
    }

    public TValue this[TKey key]
    {
        get
        {
            return ((IDictionary<TKey, TValue>)dictionary)[key];
        }

        set
        {
            ((IDictionary<TKey, TValue>)dictionary)[key] = value;
        }
    }

    public void OnBeforeSerialize()
    {
        keys.Clear();
        values.Clear();
        foreach (KeyValuePair<TKey, TValue> pair in this)
        {
            keys.Add(pair.Key);
            values.Add(pair.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        dictionary = new Dictionary<TKey, TValue>();

        if (keys.Count != values.Count)
        {
            throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable.", keys.Count, values.Count));
        }

        for (int i = 0; i < keys.Count; i++)
        {
            Add(keys[i], values[i]);
        }
    }

    public void Add(TKey key, TValue value)
    {
        ((IDictionary<TKey, TValue>)dictionary).Add(key, value);
    }

    public bool ContainsKey(TKey key)
    {
        return ((IDictionary<TKey, TValue>)dictionary).ContainsKey(key);
    }

    public bool Remove(TKey key)
    {
        return ((IDictionary<TKey, TValue>)dictionary).Remove(key);
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return ((IDictionary<TKey, TValue>)dictionary).TryGetValue(key, out value);
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        ((IDictionary<TKey, TValue>)dictionary).Add(item);
    }

    public void Clear()
    {
        ((IDictionary<TKey, TValue>)dictionary).Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return ((IDictionary<TKey, TValue>)dictionary).Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        ((IDictionary<TKey, TValue>)dictionary).CopyTo(array, arrayIndex);
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return ((IDictionary<TKey, TValue>)dictionary).Remove(item);
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return ((IDictionary<TKey, TValue>)dictionary).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IDictionary<TKey, TValue>)dictionary).GetEnumerator();
    }
}
使用UnityEngine;
使用System.Collections.Generic;
使用系统集合;
[系统可序列化]
公共类SerializableDictionary:IDictionary、ISerializationCallbackReceiver
{
[序列化字段]
私有列表密钥=新列表();
[序列化字段]
私有列表值=新列表();
私有字典=新字典();
公共ICollection密钥
{
得到
{
返回((IDictionary)字典)。键;
}
}
公共ICollection值
{
得到
{
返回((IDictionary)dictionary).value;
}
}
公共整数计数
{
得到
{
返回((IDictionary)dictionary).Count;
}
}
公共图书馆是只读的
{
得到
{
return((IDictionary)dictionary).IsReadOnly;
}
}
公共TValue此[TKey]
{
得到
{
返回((IDictionary)字典)[key];
}
设置
{
((IDictionary)dictionary)[key]=值;
}
}
public void OnBeforeSerialize()
{
键。清除();
value.Clear();
foreach(此处为KeyValuePair对)
{
keys.Add(pair.Key);
Value.Add(pair.Value);
}
}
反序列化()后的公共无效
{
字典=新字典();
if(keys.Count!=values.Count)
{
抛出新的System.Exception(string.Format(“反序列化后有{0}个键和{1}个值。请确保键和值类型都是可序列化的。”,keys.Count,values.Count));
}
对于(int i=0;i