正确设置Unity SerializedProperty值

时间:2014-10-08 20:03:45

标签: python unity3d ironpython

我正在使用IronPython在Unity3d项目中进行(仅限编辑器)清理工作。除了一个令人恼火的问题之外,这种方法很有效。

我有一个Python包装器类隐藏了使用SerializedProperties的C#详细程度:

class PropertyProxy(object):
    PROPTYPES = {
        SerializedPropertyType.Integer:"intValue",
        SerializedPropertyType.Boolean:"boolValue",
        SerializedPropertyType.Float:"floatValue",
        SerializedPropertyType.String:"stringValue",
        SerializedPropertyType.Color:"colorValue",
        SerializedPropertyType.ObjectReference:"objectReferenceValue",
        SerializedPropertyType.LayerMask:"objectReferenceValue",
        SerializedPropertyType.Enum:"enumValueIndex",
        SerializedPropertyType.Vector2:"vector2Value",
        SerializedPropertyType.Vector3:"vector3Value",
        SerializedPropertyType.Vector4:"vector4DValue",
        SerializedPropertyType.Rect:"rectValue",
        SerializedPropertyType.ArraySize:"arraySize",
        SerializedPropertyType.Character:"objectReferenceValue",
        SerializedPropertyType.AnimationCurve:"animationCurveValue",
        SerializedPropertyType.Bounds:"boundsValue",
        SerializedPropertyType.Gradient:"objectReferenceValue",
        SerializedPropertyType.Generic:"objectReferenceValue"
     }


    def __init__(self, owner):
        self.owner = owner
        self.prop_path = self.PROPTYPES[owner.propertyType]

    def __repr__(self):
        return self.owner.serializedObject.targetObject.name +"." + self.owner.propertyPath


    @property
    def value(self):
        if self.owner.isArray:
            return []
        else:
            return getattr(self.owner, self.prop_path)

    @value.setter
    def set_value(self, val):
        setattr(self.owner, self.prop_path, val)
        self.owner.serializedObject.ApplyModifiedProperties()

get功能正常,并返回正确的值。但是,制定者抱怨道。如果您尝试设置PropertyProxy的值,我会收到错误声明我正在尝试设置只读属性。这不是真的 - 我可以这样做:

 myPropertyProxy.owner.floatValue = 2.0

没有问题,但是当设置者试图做

 setattr (myPropertyProxy.owner, 'floatValue', 2.0)

我收到错误。

我认为这是某种问题,IronPython无法为Unity方面的属性获得正确的setter,但我只是在猜测。有没有人有关于这里真正发生的事情的更多信息?

更新

颁发

setattr(myProp.owner, 'floatValue', 2.0)
myProp.owner.serializedObject.ApplyModifiedProperties()

直接 - 即外面类 - 工作。哎呀。

更新2 如果您在没有属性装饰器的情况下调用它们,valueset_value函数将起作用:(

2 个答案:

答案 0 :(得分:2)

我不确定完全理解你要做什么,无论如何谈论SerializedProperty

如果要设置SerializedProperty的值(通常是编写自定义检查员代码),您可以采用以下几种方法:

  • 使用PropertyField自动以默认样式显示
  • 通过SerializedProperty访问字段并反序列化SerializedObject(就像您的方法一样)
  • 使用EditorGUI.[Begin|End]Property
  • 换取SerializedProperty访问权限
  • 直接访问序列化字段。

现在,每种方法都取决于具体的用例,并最终有其缺点。要记住的主要事情是 [de]序列化过程由不同的线程处理,需要知道在反序列化之前已经修改了哪个SerializedProperty

因此,在您的情况下(如果我理解正确),您需要至少调用2个函数,以使其在任何情况下都能正常工作:

  1. 在修改任何属性之前,请先调用Update(或UpdateIfDirtyOrScript,具体取决于具体情况)。这可确保您指的是一致的SerializedObject州。
  2. 修改SerializedProperty(就像你正在做的那样)
  3. 致电serializedObject.ApplyModifiedProperties(与更新中一样)
  4.   

    我认为这是IronPython无法解决的某种问题   在Unity方面获得一个属性的正确的setter,但我只是   猜测。有没有人知道这里真正发生了什么?

    我对Python知之甚少,所以我没有明确的答案,但这可能与floatValue setter referes和外部函数(可能在引擎的C ++端)有关:

    public extern float floatValue
    {
        [WrapperlessIcall]
        [MethodImpl(MethodImplOptions.InternalCall)]
        get;
        [WrapperlessIcall]
        [MethodImpl(MethodImplOptions.InternalCall)]
        set;
    }
    

答案 1 :(得分:0)

原来的问题原来是一种准红鲱鱼;如果您转换

,上面发布的代码可以使用
@property
def value(self):
    if self.owner.isArray:
        return []
    else:
        return getattr(self.owner, self.prop_path)

@value.setter
def set_value(self, val):
    setattr(self.owner, self.prop_path, val)
    self.owner.serializedObject.ApplyModifiedProperties()

更老套:

def _value(self):
    if self.owner.isArray:
        return []
    else:
        return getattr(self.owner, self.prop_path)

def _set_value(self, val):
    setattr(self.owner, self.prop_path, val)
    self.owner.serializedObject.ApplyModifiedProperties()

value = property(fget = _value, fset = _set_value)

我认为这代表了CPython和IronPython在实现@property装饰器时的分歧,因为在普通的CPython中这两者是可以互换的。