mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 03:47:13 +08:00
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/56
117 lines
5.8 KiB
C#
117 lines
5.8 KiB
C#
using UnityEngine;
|
||
using System;
|
||
using System.Reflection;
|
||
|
||
// 确保你已经通过 Package Manager 或手动导入了 Newtonsoft.Json
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Serialization;
|
||
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;
|
||
}
|
||
string 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)
|
||
{
|
||
JsonProperty 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;
|
||
}
|
||
}
|