我有一个名为serializableVector2的类:
[Serializable]
class serializableVector2
{
public float x, y;
public serializableVector2(int x, int y)
{
this.x = x;
this.y = y;
}
}
我有一个名为savedMapTile的结构:
[Serializable]
struct savedMapTile
{
public oreInstance ore;
public int backgroundTileId;
public int playerId;
public tree tree;
}
我有一个使用这两个类的字典:
[SerializeField]
Dictionary<serializableVector2, savedMapTile> savedTiles;
我正在尝试加载此字典修改它,然后使用序列化再次保存它。
我像这样反序列化字典:
FileStream f = File.Open(saveFileName, FileMode.Open);
BinaryFormatter b = new BinaryFormatter();
savedTiles = (Dictionary<serializableVector2, savedMapTile>)b.Deserialize(f);
f.Close();
我正在将它序列化:
FileStream f = File.Open(saveFileName, FileMode.Create);
BinaryFormatter b = new BinaryFormatter();
b.Serialize(f, savedTiles);
f.Close();
但是,当我尝试访问字典中我知道应该存在的元素时,我收到以下错误:
System.Collections.Generic.KeyNotFoundException:给定的密钥不是 出现在字典中。
运行此代码时出现此错误:
id = (savedTiles[new serializableVector2(-19,13)].backgroundTileId);
我觉得很奇怪的是,我能够打印出整个字典键及其值。这是我获取Vector2的值-19和13的地方。我打印键和值如下:
for (int i = 0; i < 100; i++ )
{
UnityEngine.Debug.Log(vv[i].x +" "+vv[i].y);
UnityEngine.Debug.Log(x[i].backgroundTileId);
}
此时我真的很难过,我不知道发生了什么事。我可以看到文件保存在Windows资源管理器中,我可以访问字典中的键和值,但我似乎无法正确使用它。同样重要的是要注意,当我在字典上使用.Contains()方法的方式与我尝试访问值的方式类似时,它总是返回false。
这是针对Unity 5项目,在Windows 8.1上运行的visual studio中使用C#。
答案 0 :(得分:0)
将serializableVector2
从class
更改为struct
,您应该能够在词典中找到相应内容。如果我有这个错误,有人可能会纠正我,但据我所知,Dictionary
将在密钥上调用GetHashCode
并使用该代码将项目存储在字典中。如果使用相同的x和y坐标创建类的两个实例并调用GetHashCode
,您将看到两个实例产生不同的哈希代码。如果将其更改为struct
,则会生成相同的哈希码。我相信这是导致你找到“未找到钥匙”问题的原因。在一个有点相关的说明中,构造函数对x和y采用int
并将它们存储为浮点数似乎很奇怪。您可能需要考虑更改构造函数以使用float
。
[Serializable]
struct serializableVector2
{
public float x, y;
public serializableVector2(float x, float y)
{
this.x = x;
this.y = y;
}
}
答案 1 :(得分:0)
您有两个问题:
serializableVector2
是依赖于默认的相等和散列方法的类。默认值使用引用相等性,这样只有指向同一对象的变量才会相等并返回相同的哈希值。serializableVector2
可能与原始值不同。建议的解决方案:
覆盖GetHashCode
课程的Equals
和serializableVector2
。执行比较和散列时,将浮点数舍入到预期值范围的32位浮点精度范围内。你可以依赖6个以上的精确数字(在同一范围内),所以如果你的世界是+ = 1000单位,我相信你可以安全地舍入到3个小数点。
GetHashCode示例(未经测试):
public override int GetHashCode() {
return Math.Round(x,3).GetHashCode() ^ Math.Round(y,3).GetHashCode();
}