从json到ScriptableObject时通用类型(object)的处理

拿配置表的实现方式来说,
json查看清晰,修改方便(复制大法、ai生成)。但是读出来需要反序列化,用反射把表里的字段映射到目标类的成员上,消耗较大。
ScriptableObject读取代价小,读出来就是目标类型。但是配置量较大时操作繁琐,可读性也差(配置是长度好几十的数组,每一条又是个数据类,不可能纯手动编辑)。

之前看到有人在Editor目录下放了json、写脚本来读取json反序列化出对象,再拿这个对象序列化生成ScriptableObject到Runtime目录,似乎是一种两全其美的方式。
于是试了一下,遇到一个问题:
json过于灵活,一个json数组中可以上一个元素是int,下一个元素是int[]。那么这种字段反序列化出来的目标类型对应的目标成员就只能是object或者JToken这种通用的类型。
这样本来没啥问题,然而ScriptableObject就没那么大度了,object等通用类型无法再次存入它。虽然反序列化出来的对象可以直接对object成员进行赋值,能赋值进去,但是当AssetDatabase.SaveAssets()后,再读出来发现本地生成的ScriptableObject里那个字段依然是null。你以为赋值成功了,实际并没有保存。

没啥太好的解决方案。只能是在目标类型里额外加一个能兼容多种情况的成员。比如成员object a可能是int和int[],那就额外加一个int[] b。a可能是int和string,那b就是string。在json反序列化完成后解析a来赋值b,将b存入ScriptableObject,需要用时以b的类型为准。
这个时机就是OnDeserialized的时候。

 			public object num;  //注意:从json反序列化时,生成object是可以的,但是object无法再次序列化存入ScriptableObject。

 			public int[] range; //所以在存ScriptableObject时统一用数组。
            
            // 反序列化时,将object类型生成int[]。
            [OnDeserialized]
            internal void OnDeserializedMethod(StreamingContext context)
            {
                if (num is int item)
                {
                    range= new int[] { item };
                }
                else if (num is long l)
                {
                    range= new int[] { (int)l };
                }
                else if (num is JArray array)
                {
                    range= array.ToObject<int[]>();
                }
            }

虽然看起来多麻烦了一个小函数的程度,但是其实不管是只用json还是只用SO都绕不开业务上的类型兼容问题,只不过它们的麻烦之处不在构建这,可能在写配置时 可能在使用配置时。所以总的来说这样还是比较好用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值