使用Unity 5.0.1f1,protobuf-net r668。
我使用Visual Studio 2013设置了一个protobuf序列化程序dll,设置为框架“Unity .Net 3.5子集基类库”(我也尝试过.Net 3.5,结果相同)。我有4个父类数据类型要序列化:两个相当简单的类型,两个更复杂的一些泛型。两个简单的序列化没有问题,而另外两个给我以下错误:
for (var i: Number = 0; i < mySaveNewT.data.myNText; ++i) {
newText = new tbox();
newText.x = -220;
newText.y = -513 + i * 69 + 0 * 3.8;
VWD.addChild(newText);
}
通过设置Exception saving savegame: Invalid IL code in NVSavegameSerializer:Write (CityBuilder.CBMap/InventoryEntryArray,ProtoBuf.ProtoWriter): IL_0035: call 0x06000001
at NVSavegameSerializer.Write (CityBuilder.Buildings , ProtoBuf.ProtoWriter ) [0x00000] in <filename unknown>:0
at NVSavegameSerializer.Write (CityBuilder.CBMap , ProtoBuf.ProtoWriter ) [0x00000] in <filename unknown>:0
at NVSavegameSerializer.Serialize (Int32 , System.Object , ProtoBuf.ProtoWriter ) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.SerializeCore (ProtoBuf.ProtoWriter writer, System.Object value) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.Serialize (System.IO.Stream dest, System.Object value, ProtoBuf.SerializationContext context) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.Serialize (System.IO.Stream dest, System.Object value) [0x00000] in <filename unknown>:0
at Nova.NVBSavegame.DoSave () [0x001ed] in C:\...\NVBSavegame.cs:118
,我尝试使用编译器选项来定位.Net1而不是.Net2,但结果是相同的。
以下是异常中提到的地方的片段(InventoryEntryArray只是因为Unity无法序列化数组阵列而存在):
MetaDataVersion = 0x10000;
以下是dll的生成方式:
[Serializable][ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class CBMap
{
...
[Serializable][ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public struct InventoryEntryArray
{
public CBMap.InventoryEntry[] a;
public CBMap.InventoryEntry this[int i] { get { return a[i]; } set { a[i] = value; } }
public InventoryEntryArray(int count) { a = new CBMap.InventoryEntry[count]; }
}
...
[Serializable][ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public struct InventoryEntry : CXPoolIndex
{
public int _index;
public int Index { get { return _index; } set { _index = value; } }
public static bool operator==(InventoryEntry a, InventoryEntry b) { return a._index == b._index; }
public static bool operator!=(InventoryEntry a, InventoryEntry b) { return !(a == b); }
public override bool Equals(System.Object o) { if (!(o is InventoryEntry)) return false; return this == (InventoryEntry)o; }
public override int GetHashCode() { return _index; }
public InventoryEntry(int ix) { _index = ix; }
... [some properties, a Reset() function]
}
...
[Serializable][ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Buildings
{
public CXPool<Building> pool;
... [no constructor, other variables, CXPool is an interface]
public float[] repairFactor;
[CXSoAFieldConstructor(5)]
public CBMap.InventoryEntryArray[] inventory;
[^ here's the field mentioned in the exception]
}
}
对这个问题有什么看法吗?
谢谢。
以下是peverify的结果:
var model = RuntimeTypeModel.Create();
model.AutoCompile = false;
model.AllowParseableTypes = true;
model.AutoAddMissingTypes = true;
model.Add(typeof(CXPoolIndex), true)
.AddSubType(1000, typeof(CBMap.Building))
.AddSubType(1001, typeof(CBMap.Captain))
.AddSubType(1002, typeof(CBMap.InventoryEntry))
.AddSubType(1003, typeof(CBMap.Tile))
;
model.Add(typeof(CXPool<CBMap.Building>), true).AddSubType(1000, typeof(CXPoolSwap<CBMap.Building>));
model.Add(typeof(CXPool<CBMap.Captain>), true).AddSubType(1001, typeof(CXPoolSwap<CBMap.Captain>));
model.Add(typeof(CXPool<CBMap.InventoryEntry>), true).AddSubType(1002, typeof(CXPoolSwap<CBMap.InventoryEntry>));
model.Add(typeof(CXPool<CBMap.Tile>), true).AddSubType(1003, typeof(CXPoolSwap<CBMap.Tile>));
model.Add(typeof(CBMap), true);
model.Add(typeof(CBSimulation), true);
model.Add(typeof(NVSavegame.Data), true);
model.Add(typeof(NVSavegame.BuildingSave), true);
string typename = "NVSavegameSerializer";
var opt = new RuntimeTypeModel.CompilerOptions();
opt.TypeName = typename;
opt.OutputPath = typename + ".dll";
//opt.MetaDataVersion = 0x10000;
model.Compile(opt);