Unity的AnimationCurve序列化/分配有什么不同?为什么我的示例失败了?

时间:2019-11-08 17:19:24

标签: c# unity3d serialization

摘要

在使用Unity的AnimationCurve尝试以下操作时,我遇到了意外的问题:

x = A (via serialization/deserialization)
y = x
x = B (via serialization/deserialization)

Assert that y equals A

如伪代码所示,我希望y等于A。但是,这似乎不适用于AnimationCurve类型。为什么会这样?


完整说明

为了说明正在发生的事情,我使用NUnit为此设置了一个测试用例。如下所述,该测试无法通过。

public class AnimationCurveMonoBehaviour: MonoBehaviour
{
    public AnimationCurve myCurve;
}
[Test]
public void SetValueViaSerialization_SetsAThenB_HasValueAInTheMiddle()
{
    // INITIALIZATION
    GameObject gameObject = new GameObject();
    AnimationCurveMonoBehaviour animationCurveMonoBehaviour = gameObject.AddComponent<AnimationCurveMonoBehaviour>();

    AnimationCurve animationCurveA = new AnimationCurve(new Keyframe(0, 1));
    AnimationCurve animationCurveB = new AnimationCurve(new Keyframe(0, 2));

    // EXECUTION
    this.SetAnimationCurveValue(animationCurveMonoBehaviour, animationCurveA);
    AnimationCurve sample = animationCurveMonoBehaviour.myCurve;
    this.SetAnimationCurveValue(animationCurveMonoBehaviour, animationCurveB);

    // ASSERTION
    Assert.AreEqual(animationCurveA, sample); // FAILS
}

private void SetAnimationCurveValue(AnimationCurveMonoBehaviour animationCurveMonoBehaviour, AnimationCurve animationCurve)
{
    SerializedObject serializedObject = new SerializedObject(animationCurveMonoBehaviour);
    SerializedProperty sut = serializedObject.FindProperty("myCurve");
    sut.animationCurveValue = animationCurve;
    serializedObject.ApplyModifiedProperties();
}

通过对下面列出的所有类型运行相同的测试(具有适当的类型修改),测试将通过。

int
bool
float
string
Color
Vector2
Vector3
Vector4
Rect
Bounds
Quaternion
Vector2Int
Vector3Int
RectInt
BoundsInt
GameObject
TMP_FontAsset
Sprite

但是真正奇怪的是,使用AnimationCurve时,以下类似测试也可以按预期工作:

//...
// EXECUTION
this.SetAnimationCurveValue(animationCurveMonoBehaviour, animationCurveA);
AnimationCurve sample = animationCurveMonoBehaviour.myCurve;
Assert.AreEqual(animationCurveA, sample); // PASSES
//...
//...
// EXECUTION
this.SetAnimationCurveValue(animationCurveMonoBehaviour, animationCurveA);
this.SetAnimationCurveValue(animationCurveMonoBehaviour, animationCurveB);
AnimationCurve sample = animationCurveMonoBehaviour.myCurve;
Assert.AreEqual(animationCurveB, sample); // PASSES
//...

AnimationCurve和我的示例有什么不同?

1 个答案:

答案 0 :(得分:1)

质量检查支持的答案是:

  

通常,对于基本类型(例如“ int”,“ bool”,“ string”等),应保留AreEqual。   通常,对于任何包含对象或对象的对象,它都无法很好地工作。   尽管Object是一个类,但它并不打算在脚本中广泛使用。

     

https://docs.unity3d.com/ScriptReference/Assertions.Assert.AreEqual.html包含许多与此有关的有用信息,其中提到了System.Object对象的用法,而不是UnityEngine.Object对象的用法(而Animation Curve正是这样)。