Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Test/jsonRule.cs

100 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using UnityEngine;
// 确保你已经通过 Package Manager 或手动导入了 Newtonsoft.Json
using Object = UnityEngine.Object; // 用于自定义序列化,可选但推荐
public class UnityObjectConverter : JsonConverter<Object>
{
public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
{
if (value == null)
writer.WriteNull();
else
// 对于 Unity 对象,最简单的序列化方式是它们的名称。
// 也可以选择序列化 InstanceID 或 Asset Path (在编辑器环境下)。
writer.WriteValue(value.name);
// 如果你需要 Asset Path (仅在 Unity 编辑器中可用)
// #if UNITY_EDITOR
// string path = UnityEditor.AssetDatabase.GetAssetPath(value);
// writer.WriteValue(path);
// #else
// writer.WriteValue(value.name);
// #endif
}
public override Object ReadJson(JsonReader reader, Type objectType, Object existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var objectIdentifier = reader.Value?.ToString();
if (string.IsNullOrEmpty(objectIdentifier)) return null;
// 示例反序列化:尝试从 Resources 文件夹加载同名对象
// 这需要你的对象位于 "Resources/" 路径下
// 并且 objectType 必须是正确的目标类型 (如 Sprite, GameObject等)
return Resources.Load(objectIdentifier, objectType);
// 如果你的对象不是通过 Resources 加载的,你可能需要自定义查找逻辑
// 例如:
// if (objectType == typeof(Sprite))
// {
// // 假设你有一个方法可以根据名称找到 Sprite Asset
// return MyAssetManager.LoadSpriteByName(objectIdentifier);
// }
// return null;
}
}
public class UnityPropertyContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
// --- 1. 处理 Unity 数学结构体及其循环引用问题 ---
// Vector3, Vector2, Bounds, Rect 都是 struct但它们的某些属性返回新实例导致 JsonConvert 误判循环。
if (member.DeclaringType == typeof(Vector3) || member.DeclaringType == typeof(Vector2))
{
// 明确忽略 normalized, magnitude, sqrMagnitude 等计算属性
if (member.Name == "normalized" || member.Name == "magnitude" || member.Name == "sqrMagnitude")
property.ShouldSerialize = instance => false;
}
else if (member.DeclaringType == typeof(Bounds))
{
// Bounds 结构体在内部引用 Vector3也可能有一些我们不希望序列化的计算属性
// 例如min/max 可以通过 center 和 extents 计算得出,通常不需单独序列化
if (member.Name == "min" || member.Name == "max") property.ShouldSerialize = instance => false;
}
else if (member.DeclaringType == typeof(Rect))
{
// Rect 也有一些计算属性,如果不需要可以忽略
// 例如xMax, yMax, center, position, size
if (member.Name.EndsWith("Max") || member.Name == "center" || member.Name == "position" ||
member.Name == "size") property.ShouldSerialize = instance => false;
}
// --- 2. 处理 UnityEditor 命名空间中的类型 (在运行时通常不序列化) ---
// 这些通常是编辑器专属数据,不应包含在运行时序列化中。
if (property.DeclaringType != null && property.DeclaringType.Namespace != null &&
property.DeclaringType.Namespace.StartsWith("UnityEditor")) property.ShouldSerialize = instance => false;
// --- 3. 处理 Unity.Mathematics 命名空间中的类型 (如果有使用 DOTS/Job System) ---
// 尽管 Unity.Mathematics 类型通常没有循环引用,但如果你只想序列化原始字段,可以这样做。
// if (property.DeclaringType != null && property.DeclaringType.Namespace != null && property.DeclaringType.Namespace.StartsWith("Unity.Mathematics"))
// { /* ... */ }
// --- 4. 确保 Unity Object 引用由专门的 Converter 处理,而不是默认序列化器 ---
// 虽然我们已经提供了 UnityObjectConverter但这一步可以作为补充。
// 如果某个属性的类型是 UnityEngine.Object 或其派生,但又没有显式地被 Converter 捕获
// 我们可以禁用其默认序列化,以避免尝试序列化内部数据。
// 但由于我们注册了 UnityObjectConverter它应该会优先处理。
// 这一部分通常是多余的,除非你的 Converter 只能处理特定的 Unity Object 类型 (例如只处理 Sprite)。
/*
if (typeof(Object).IsAssignableFrom(property.PropertyType) && !property.PropertyType.IsPrimitive && !property.PropertyType.IsEnum)
{
// 除非你有一个针对特定 Unity Object 类型的自定义转换器,否则通常不应该直接序列化它们。
// 这里我们假设 UnityObjectConverter 会处理所有 Object 类型。
// 如果你有特定的 Object 类型需要排除,可以在这里添加逻辑。
}
*/
return property;
}
}