我正在编写一种扩展方法来简化SerializedProperty
的使用这个想法是该方法的用户应该能够设置SerializedProperty
的值而不必担心类型。如下例所示,应根据serializedProperty
和myValue
的类型来处理正确的类型。
常规使用SerializedProperty
(Unity方式)的示例:
serializedProperty.intvalue = myIntvalue;
serializedProperty.floatvalue = myFloatvalue;
serializedProperty.boolValue = myBoolValue;
...
我的SerializedProperty
方法扩展的预期语法
serializedProperty.Setvalue(myValue);
此SerializedProperty
方法扩展的当前实现
public static void Setvalue<tvalue>(this SerializedProperty property,tvalue value)
{
if (property.hasMultipleDifferentvalues)
throw new ArgumentOutOfRangeException();
Type parentType = property.serializedObject.targetObject.GetType();
FieldInfo fieldInfo = parentType.GetField(property.propertyPath);
fieldInfo.Setvalue(property.serializedObject.targetObject,value);
}
问题:
此实现不调用OnValidate
Unity回调。经常使用(mySerializedProperty.intvalue = myInt
)。
我的问题:有什么方法可以强制Unity在OnValidate
上调用SerializedProperty
方法?
我曾考虑过自己通过反射来调用OnValidate
,但是由于这已经在Unity中实现,所以我想知道是否有办法将SerializedProperty
标记为已更改或类似内容。
为测试此行为,我编写了以下测试(NUnit):
private IntMonoBehaviourMock _mockInstance;
[SetUp]
public void CallBeforeEachTest()
{
GameObject gameObject = new GameObject();
this._mockInstance = gameObject.AddComponent<IntMonoBehaviourMock>();
}
[Test]
// This test fails for the current implementation
public void Setvalue_ToDifferentvalue_OnValidateCalledOnce()
{
this.SetvalueOfSUT(0x1CE1CE);
int numCallsBefore = this._mockInstance.NumTimesValidateCalled;
this.SetvalueOfSUT(0xBABE);
int numCallsAfter = this._mockInstance.NumTimesValidateCalled;
int actualNumCalls = numCallsAfter - numCallsBefore;
Assert.AreEqual(1,actualNumCalls); // Fails
}
private void SetvalueOfSUT(int value)
{
string fieldName = "publicSerializedField"
SerializedObject serializedObject = new SerializedObject(this._mockInstance);
SerializedProperty sut = this._serializedObject.FindProperty(fieldName);
// This is the call to function being tested!
// Swapping this for sut.intvalue = value,makes the test pass.
// (But the purpose is to write a function that handles any type correctly)
sut.Setvalue(value);
this._serializedObject.ApplyModifiedProperties();
}
我在测试中使用的 IntMonoBehaviourMock 的实现是:
public class IntMonoBehaviourMock: MonoBehaviour
{
[SerializeField]
public int publicSerializedField = default;
public int NumTimesValidateCalled { get; private set; }
protected void OnValidate()
{
this.NumTimesValidateCalled++;
}
}
测试结果为:
Expected: 1
But was: 0