2016-09-30 26 views
1

我正在爲使用JSON .NET的Unity3D遊戲編寫自定義序列化程序。我們可以有一些GameObject類型的字段,它是一個Unity3D內部類,它將引用遊戲中的資源資源。我們需要能夠僅通過它的'GUID字符串序列化GameObject屬性。使用這些信息,我們可以利用Unity3D的AssetDatabase來檢索資產並將其加載到屬性中。我如何通過GUID自定義序列化GameObject引用?

public class Blueprint { 
    public IList<IComponent> Components = new List<IComponent>(); 
} 

public class UnityPrefabs : IComponent { 
    public GameObject ViewPrefab; 
    public GameObject ModelPrefab; 
} 

我使用的是.NET JSON序列化的方法:

public void Serialize(Blueprint blueprint) { 
    blueprintData = JsonConvert.SerializeObject(blueprint, Formatting.Indented, 
     new JsonSerializerSettings() 
     { 
      TypeNameHandling = TypeNameHandling.All, 
      Converters = new List<JsonConverter>() { new UnityPrefabConverter() }, 
      //ContractResolver = new ConverterContractResolver() 
     }); 
} 

public Blueprint Deserialize() { 
    var blueprint = string.IsNullOrEmpty(blueprintData) 
     ? new Blueprint() : JsonConvert.DeserializeObject<Blueprint>(blueprintData, 
     new JsonSerializerSettings() 
     { 
      TypeNameHandling = TypeNameHandling.All, 
      //TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, 
      NullValueHandling = NullValueHandling.Include, 
      Converters = new List<JsonConverter>() { new UnityPrefabConverter() }, 
     }); 
    return blueprint; 
} 

我沒有作出嘗試編寫自定義轉換器,但是Write()方法不會被調用,而只讀取()是:

public class UnityPrefabConverter : JsonConverter { 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var go = value as GameObject; 
     var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(go)); 

     writer.WriteValue(guid); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     Debug.Log("Reading json"); 
     if (existingValue == null) return null; 

     return AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(existingValue as string)); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(GameObject)); 
    } 
} 

我能找到現在唯一的奇異之處在於它不是序列化的JSON類型的遊戲對象字段:

{\r\n \"$type\": \"CubeBasic.Model.UnityPrefabs, Assembly-CSharp\",\r\n \ \"ViewPrefab\": \"\",\r\n \"ModelPrefab\": null\r\n }\r\n \ ]\r\n }\r\n}"

回答

1

你的轉換器不叫,因爲序列化過程中, objectType是被序列化的GameObject的實際類型,因此是GameObject的子類型。修改CanConvert使用Type.IsAssignableFrom(Type)

public override bool CanConvert(Type objectType) 
{ 
    return typeof(GameObject).IsAssignableFrom(objectType); 
} 

而且,在你ReadJson,你可能不想檢查existingValue是否爲空,而不是你想做的事:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    Debug.Log("Reading json"); 
    if (reader.TokenType == JsonToken.Null) 
     return null; 
    var guid = (string)JToken.Load(reader); // Load the GUID value 

    return AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid)); 
} 

existingValue是一個參考無論POCO是在包含對象的構造函數中預先分配的。

既然你已經編寫了你自己的JsonConverterGameObjectobject types將不會被編寫,除非你明確在轉換器中這樣做。但是,由於您實際上並未反序列化該對象,但僅從某個數據庫獲取該對象,所以我認爲這不是必需的。

+0

注 - 我不是團結開發者,所以可能會有其他問題。 – dbc

+0

不,那太棒了。鍛鍊了魅力。 –

1

你應該嘗試Newtonsoft(你可以將其添加到您的項目作爲NuGet包),你可以寫一個通用的JSonSerializer類

using Newtonsoft.Json; 

public class JSonSerializer : IObjectSerializer 
{ 
    public string ToJson<T>(T obj) 
    { 
     return JsonConvert.SerializeObject(obj); 
    } 

    public T FromJson<T>(string json) 
    { 
     try 
     { 
      return JsonConvert.DeserializeObject<T>(json); 
     } 
     catch(JsonReaderException e) 
     { 
      throw new ObjectSerializationException(e); 
     } 
    } 
}