ºÇ½ª¹¹¿·¡§
orika_ex_miyako 2024ǯ01·î04Æü(ÌÚ) 18:42:12ÍúÎò
¡¡PlayFab ¤Ê¤É¤Î¥µ¡¼¥Ð¡¼¤ËÊݸ¤·¤¿¥Ç¡¼¥¿¤Î¿¤¯¤Ï Json ·Á¼°¤Î¥Õ¥¡¥¤¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
¤½¤Î¤¿¤á¡¢¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤ä¥²¡¼¥àÆâ¤Î¾õÂÖ¤ò¸úΨŪ¤«¤Ä¡¢Àµ¤·¤¤ÊýË¡¤ò»È¤Ã¤ÆÊݸ¤ª¤è¤ÓÆɤ߹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡£
¡¡Ëܵ»ö¤Ç¤Ï¡¢Json.NET¤ÈUniRx¤ÎReactiveProperty¤òÁȤ߹ç¤ï¤»¤Æ¡¢¥·¥ê¥¢¥é¥¤¥º¤È¥Ç¥·¥ê¥¢¥é¥¤¥º¤ò¹Ô¤¦¼êË¡¤ò²òÀ⤷¤Þ¤¹¡£
¡¡¡¦Unity¥²¡¼¥àÆâ¤Î¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òJson·Á¼°¤ÇÊݸ ¡¡¡¦Êݸ¤µ¤ì¤¿Json¥Ç¡¼¥¿¤òÆɤ߹þ¤ó¤ÇUnity¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º ¡¡¡¦¥ê¥¢¥¯¥Æ¥£¥Ö¥×¥í¥°¥é¥ß¥ó¥°¥é¥¤¥Ö¥é¥êUniRx¤ÎReactiveProperty¤ò»È¤Ã¤Æ¸úΨŪ¤Ê¥Ç¡¼¥¿´ÉÍý
¡¡Ä̾ï¤ÎJson.NET¤Ç¤ÏReactiveProperty¤Î¥Ç¥·¥ê¥¢¥é¥¤¥º¤¬½ÐÍè¤Þ¤»¤ó¡£
¡¡Î㤨¤Ð¡¢°Ê²¼¤Î¤è¤¦¤ÊReactiveProperty¤ò»ý¤Ä¥¯¥é¥¹¤¬¤¢¤ë¤È¤·¤Þ¤¹¡£
[System.Serializable] public class PlayerData { public ReactiveProperty<int> Score { get; set; } // ¥³¥ó¥¹¥È¥é¥¯¥¿ public PlayerData() { // ½é´ü²½¤Ê¤ÉɬÍפ˱þ¤¸¤Æ½èÍý¤òÄɲà Score = new ReactiveProperty<int>(); } }
¡¡¤³¤Î¥¯¥é¥¹¤òÄ̾ï¤ÎJson.NET¤Ç¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤è¤¦¤È¤¹¤ë¤È¡¢¤¦¤Þ¤¯¤¤¤«¤º¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤¹¡£
ArgumentException: Could not cast or convert from System.Int64 to UniRx.ReactiveProperty`1[System.Int32]. Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable (System.Object value, System.Type initialType, System.Type targetType)
JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Int32' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly. To fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
¡¡Json.NET¤Ë¤ª¤¤¤Æ¡¢ReactiveProperty ¤òÀµ¤·¤¯¥Ç¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¤¿¤á¤Ë¤Ï¡¢JsonConveter ¥¯¥é¥¹¤ò·Ñ¾µ¤·¤¿
ReactivePropertyConverter ¤òºîÀ®¤·¡¢ReadJson ¥á¥½¥Ã¥É¤È WriteJson ¥á¥½¥Ã¥É¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥É¤·¤Æ¼ÂÁõ¤·¤Þ¤¹¡£
¡¡°Ê²¼¤Ï¤½¤Î¥µ¥ó¥×¥ë¥³¡¼¥É¤Ç¤¹¡£
using Newtonsoft.Json; using UniRx; using System; using Newtonsoft.Json.Linq; public class ReactivePropertyConverter<T> : JsonConverter<ReactiveProperty<T>> { public override void WriteJson(JsonWriter writer, ReactiveProperty<T> value, JsonSerializer serializer) { if (value != null && value.HasValue) { // HasValue¤¬true¤Î¾ì¹ç¡¢Value¤ò½ÐÎÏ serializer.Serialize(writer, new { Value = value.Value, HasValue = true }); } else { // HasValue¤¬false¤Î¾ì¹ç¡¢null¤ò½ÐÎÏ serializer.Serialize(writer, null); } } public override ReactiveProperty<T> ReadJson(JsonReader reader, Type objectType, ReactiveProperty<T> existingValue, bool hasExistingValue, JsonSerializer serializer) { var token = JToken.Load(reader); if (token.Type == JTokenType.Null) { // JSON¤¬null¤Î¾ì¹ç¡¢¿·¤·¤¤ReactiveProperty¤òºîÀ®¤·¤ÆÊÖ¤¹ return new ReactiveProperty<T>(); } else { // JSON¤¬Ãͤò»ý¤Ã¤Æ¤¤¤ë¾ì¹ç¡¢¤½¤ÎÃͤò¸µ¤Ë¿·¤·¤¤ReactiveProperty¤òºîÀ®¤·¤ÆÊÖ¤¹ var valueToken = token["Value"]; if (valueToken != null) { var value = valueToken.ToObject<T>(serializer); return new ReactiveProperty<T>(value); } else { // "Value"¥×¥í¥Ñ¥Æ¥£¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¡¢Îã³°½èÍý¤Þ¤¿¤Ï¥Ç¥Õ¥©¥ë¥È¤Î½èÍý¤ò¹Ô¤¦ // Îã: throw new JsonSerializationException("Expected 'Value' property not found."); return new ReactiveProperty<T>(); } } } }
¡¡ReactivePropertyConverter ¥¯¥é¥¹¤Ï¡¢Å¬ÍѤ·¤¿¤¤ ReactiveProperty ¤Ë°À¾ðÊó¤òÉÕÍ¿¤¹¤ë¤³¤È¤ÇÍøÍѤǤ¤Þ¤¹¡£
¡¡Î㤨¤Ð¡¢Àè¤Û¤É¤Î PlayerData ¥¯¥é¥¹Æâ¤Î ReactiveProperty ¤Ë°À¾ðÊó¤òÉÕÍ¿¤·¤Þ¤¹¡£
[System.Serializable] public class PlayerData { [JsonConverter(typeof(ReactivePropertyConverter<int>))] // ¢«¡¡Â°À¾ðÊó¤òÉÕÍ¿ public ReactiveProperty<int> Score { get; set; } }
¡¡¤³¤ì¤Ç¥Ç¥·¥ê¥¢¥é¥¤¥º¤È¥·¥ê¥¢¥é¥¤¥º¤¬²Äǽ¤Ê ReactiveProperty ¤Ë¤Ê¤ê¤Þ¤¹¡£
¡¡¤³¤Îµ¡Ç½¤ò³èÍѤ¹¤ë¤È Json ¤¬ ReactiveProperty ¤ËŬ¤·¤¿·Á¼°¤È¤·¤ÆÊݸ¡¦Æɤ߹þ¤ß¤µ¤ì¤Þ¤¹¡£
{ "Score": { "Value": 0, "HasValue": true } }
¡¡ÍøÍѤ¹¤ë¾ì¹ç¤Ë¤Ï¡¢²¼µ¤Î¤è¤¦¤ËÍøÍѤ·¤Þ¤¹¡£
public class GameManager : MonoBehaviour { void Start() { // ¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤ÎºîÀ®¤È½é´ü²½ PlayerData player = new PlayerData { Score = new (1000) }; // ¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òJson¤Ë¥·¥ê¥¢¥é¥¤¥º string json = JsonConvert.SerializeObject(player); // Json¥Ç¡¼¥¿¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¿·¤·¤¤¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òºîÀ® PlayerData loadedPlayer = JsonConvert.DeserializeObject<PlayerData>(json); // ¥Ç¥·¥ê¥¢¥é¥¤¥º¸å¤Î¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤Î¥¹¥³¥¢¤òɽ¼¨ Debug.Log("Loaded Player Score: " + loadedPlayer.Score.Value); } }
¡¡¤³¤Î¥µ¥ó¥×¥ë¥³¡¼¥É¤Ç¤Ï¡¢ReactivePropertyConverter¤ò»ÈÍѤ·¤ÆJson.NET¤¬ReactiveProperty¤òÀµ¤·¤¯½èÍý¤Ç¤¤ë¤è¤¦¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
¡¡¤³¤ì¤Ë¤è¤ê¡¢UniRx¤ÎReactiveProperty¤ò´Þ¤à¥ª¥Ö¥¸¥§¥¯¥È¤ò´Êñ¤ËJson·Á¼°¤ÇÊݸ¡¦Æɤ߹þ¤ß¤Ç¤¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
¡¡¥¢¥×¥í¡¼¥ÁÊýË¡¡¤Î¾ì¹ç¡¢¤¹¤Ç¤ËÊݸ¤µ¤ì¤Æ¤¤¤ë Json ¥Ç¡¼¥¿¤¬Â¸ºß¤·¤Æ¤¤¤ë¤È¡¢
¥Õ¥¡¥¤¥ë¤Î·Á¼°¤¬¹ç¤ï¤Ê¤¤¤¿¤á¥¨¥é¡¼¤È¤Ê¤ê¤Þ¤¹¡£¤è¤Ã¤Æ¡¢ÅÓÃ椫¤é¤Î±¿ÍÑÊѹ¹¤Ï½ÐÍè¤Þ¤»¤ó¡£
¡¡ºÇ½é¤«¤é¥¢¥×¥í¡¼¥ÁÊýË¡¡¤ÇÀ©ºî¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤ÏÌäÂꤢ¤ê¤Þ¤»¤ó¤¬¡¢
¤¹¤Ç¤Ë Json ¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥Õ¥¡¥¤¥ë¤Î·Á¼°¤Ï¤½¤Î¤Þ¤Þ¤Ë¤·¤Æ¤ª¤¡¢
Êݸ¤¹¤ë¥¿¥¤¥ß¥ó¥°¤ä¡¢Æɤ߹þ¤à¥¿¥¤¥ß¥ó¥°¤Ç ReactiveProperty ¤ËÂбþ¤µ¤»¤ëÊýË¡¤¬¤è¤¤¤Ç¤·¤ç¤¦¡£
¡¡°Ê²¼¤Ï¤½¤Î¥µ¥ó¥×¥ë¥³¡¼¥É¤Ç¤¹¡£
¡¡PlayerData ¥¯¥é¥¹¤Ë¡¢Json¤Î¥Ç¥·¥ê¥¢¥é¥¤¥º¤ª¤è¤Ó¥·¥ê¥¢¥é¥¤¥º¤Î¤¿¤á¤Î¥á¥½¥Ã¥É¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£
ReactiveProperty¤ÏÈóSerializable¤È¤·¤ÆÊÝ»ý¤·¡¢Json¤Î½èÍýÁ°¸å¤ÇscoreÊÑ¿ô¤ÈscoreReactive¤ÎƱ´ü¤ò¤È¤ë¤è¤¦¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤ê¡¢Json¤Î¥·¥ê¥¢¥é¥¤¥º¡¦¥Ç¥·¥ê¥¢¥é¥¤¥º»þ¤ËReactiveProperty¤ÎÃͤâŬÀڤ˽èÍý¤Ç¤¤Þ¤¹¡£
using UnityEngine; [System.Serializable] public class PlayerData { [SerializeField] private int score; // ReactiveProperty¤ÏJsonUtility¤Ç¥·¥ê¥¢¥é¥¤¥º¤Ç¤¤Ê¤¤¤Î¤Ç¡¢ÈóSerializable¤È¤·¤ÆÊÝ»ý private ReactiveProperty<int> scoreReactive; // ReactiveProperty¤ò³°Éô¤Ë¸ø³«¤¹¤ë¤¿¤á¤Î¥×¥í¥Ñ¥Æ¥£ public IReadOnlyReactiveProperty<int> ScoreReactive => scoreReactive; // ¥³¥ó¥¹¥È¥é¥¯¥¿ public PlayerData(int initialScore) { // ½é´ü²½¤Ê¤ÉɬÍפ˱þ¤¸¤Æ½èÍý¤òÄɲà score = initialScore; scoreReactive = new ReactiveProperty<int>(score); } // ¥µ¡¼¥Ð¡¼¤«¤é¼èÆÀ¤·¤¿Json¥Ç¡¼¥¿¤òPlayerData¤ËÊÑ´¹¤¹¤ë¥á¥½¥Ã¥É public static PlayerData FromJson(string json) { PlayerData playerData = JsonUtility.FromJson<PlayerData>(json); // JsonUtility¤Ç¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤¿¸å¡¢score¤òReactiveProperty¤ËÀßÄê playerData.scoreReactive.Value = playerData.score; return playerData; } // ¥µ¡¼¥Ð¡¼¤ËÁ÷¤ë¤¿¤á¤ÎJson¥Ç¡¼¥¿¤òÀ¸À®¤¹¤ë¥á¥½¥Ã¥É public string ToJson() { // ¥µ¡¼¥Ð¡¼¤ËÁ÷¤ëºÝ¤Ë¤Ï¡¢ReactiveProperty¤ÎÃͤòscoreÊÑ¿ô¤ËÀßÄê score = scoreReactive.Value; return JsonUtility.ToJson(this); } }
¡¡¤³¤Î¾ì¹ç¤Î Json ·Á¼°¤Ï°ìÈÌŪ¤Ê·Á¼°¤Ë¤Ê¤ê¤Þ¤¹¡£
{ "score": 0 }
¡¡ÍøÍѤ¹¤ë¾ì¹ç¤Ë¤Ï¡¢²¼µ¤Î¤è¤¦¤ËÍøÍѤ·¤Þ¤¹¡£
using UnityEngine; using Newtonsoft.Json; public class GameManager : MonoBehaviour { void Start() { // TODO ¥µ¡¼¥Ð¡¼¤«¤é¼õ¤±¼è¤Ã¤¿Json¥Ç¡¼¥¿¤ò²¾Äꤹ¤ë string receivedJsonFromServer = "{ \"score\": 1500 }"; // PlayerData¤ÎFromJson¥á¥½¥Ã¥É¤ò»ÈÍѤ·¤ÆJson¥Ç¡¼¥¿¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º PlayerData loadedPlayer = PlayerData.FromJson(receivedJsonFromServer); // ¥Ç¥·¥ê¥¢¥é¥¤¥º¸å¤Î¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤Î¥¹¥³¥¢¤òɽ¼¨ Debug.Log("Loaded Player Score: " + loadedPlayer.ScoreReactive.Value); // ¿·¤·¤¤¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òºîÀ® PlayerData newPlayer = new PlayerData(2000); // PlayerData¤ÎToJson¥á¥½¥Ã¥É¤ò»ÈÍѤ·¤Æ¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òJson¤Ë¥·¥ê¥¢¥é¥¤¥º string json = newPlayer.ToJson(); // ¥·¥ê¥¢¥é¥¤¥º¤·¤¿Json¥Ç¡¼¥¿¤òɽ¼¨ Debug.Log("Serialized Player Data: " + json); // TODO ¥µ¡¼¥Ð¡¼¤ØÁ÷¿® } }
¡¡¥µ¡¼¥Ð¡¼¤«¤é¤ÎJson¥Ç¡¼¥¿¤ò²¾Äꤷ¤Æ¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¡¢¿·¤·¤¤¥×¥ì¥¤¥ä¡¼¥Ç¡¼¥¿¤òºîÀ®¤·¤Æ¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¤¤¤Þ¤¹¡£
¡¡¥²¡¼¥àÆâ¤Ç¤Ï PlayerData Æâ¤Î ReactiveProperty ¤ò³èÍѤ·¤Æ¹ØÆɽèÍý¤ò¹Ô¤¤¡¢
¥µ¡¼¥Ð¡¼¤ËÁ÷¿®¤¹¤ëÁ°¤Ë Json ¤ËÃÖ¤´¹¤¨¤Æ¤«¤éÁ÷¿®¤¹¤ë¤è¤¦¤Ë¤·¤Þ¤¹¡£
- ¥«¥Æ¥´¥ê¡§
- ¿Ê³Ø/¥¹¥¯¡¼¥ë
- ¥×¥í¥°¥é¥ß¥ó¥°
¥³¥á¥ó¥È¤ò¤«¤¯