我有一个名为HandSkeleton
的脚本,我为它编写了一个自定义编辑器。HandSkeleton
有一个类型为HandSkeletonData
的字段,它是一个ScriptableObject
。我写了一个自定义检查器,它可以将一些值从HandSkeleton
保存到它所引用的HandSkeletonData
。
这是代码:
[CustomEditor(typeof(HandSkeleton))]
public class HandSkeletonEditor : UnityEditor.Editor
{
private const string BasePath = "Assets/ScriptableObjects/HandSkeletonData";
public override void OnInspectorGUI()
{
DrawDefaultInspector();
var handSkeleton = (HandSkeleton)target;
if (GUILayout.Button("Save hand skeleton data"))
{
var handSkeletonTransform = handSkeleton.transform;
var rootName = handSkeletonTransform.root.name;
var parentName = handSkeletonTransform.parent.name;
var skeletonName = handSkeletonTransform.name;
if (handSkeleton.handSkeletonData == null)
{
var so = CreateInstance<HandSkeletonData>();
if (!AssetDatabase.IsValidFolder(BasePath + $"/{rootName}"))
AssetDatabase.CreateFolder(BasePath, rootName);
AssetDatabase.CreateAsset(so, $"{BasePath}/{rootName}/{parentName}_{skeletonName}.asset");
serializedObject.FindProperty(nameof(handSkeleton.handSkeletonData))
.objectReferenceValue = so;
serializedObject.ApplyModifiedProperties();
}
var rotations = handSkeleton.EditorInitialized.GetAllFingerSegmentRotations()
.Select(x => (Quaternion[])x.Clone())
.ToArray();
// here I change the Scriptable Object
handSkeleton.handSkeletonData.FingerSegmentRotations = rotations;
EditorUtility.SetDirty(handSkeleton.handSkeletonData);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
}
问题是对handSkeletonData
所做的更改在我刷新编辑器后丢失。我发现许多其他帖子中人们有同样的问题,但这主要是由于没有打电话EditorUtility.SetDirty()
引起的。我说错了吗?还是我做错了什么?
事实证明,问题不在于我保存Scriptable Object
的方式,而在于其中保存的内容 -Quaternions
的 2D 数组。Unity 根本不序列化 2D 数组。为了解决这个问题,我将 2D 数组更改为 1D 数组,并通过属性访问它。如果有人对这里感兴趣,这里是这个代码:
[HideInInspector] [SerializeField] private Quaternion[] fingerSegmentRotations;
public Quaternion[][] FingerSegmentRotations
{
get
{
if (fingerSegmentRotations == null || fingerSegmentRotations.Length == 0) return null;
var rotations = new Quaternion[HandSkeleton.FingerCount][];
for (var i = 0; i < HandSkeleton.FingerCount; i++)
{
rotations[i] = new Quaternion[HandSkeleton.SegmentCount];
for (var j = 0; j < HandSkeleton.SegmentCount; j++)
rotations[i][j] = fingerSegmentRotations[i * HandSkeleton.SegmentCount + j];
}
return rotations;
}
set
{
fingerSegmentRotations = new Quaternion[HandSkeleton.FingerCount * HandSkeleton.SegmentCount];
for (var i = 0; i < HandSkeleton.FingerCount; i++)
for (var j = 0; j < HandSkeleton.SegmentCount; j++)
fingerSegmentRotations[i * HandSkeleton.SegmentCount + j] = value[i][j];
}
}