[英]How to set SerializedProperty.propertyType in a CustomPropertyDrawer
我正在使用这两个库:
Unity-SerializableDictionary: https : //github.com/starikcetin/Unity-SerializableDictionary
Unity场景参考: https : //github.com/starikcetin/unity-scene-reference
基本上,可序列化的字典查看propertyType以确定属性是否可以扩展,并进行以下检查:
static bool CanPropertyBeExpanded(SerializedProperty property)
{
switch(property.propertyType)
{
case SerializedPropertyType.Generic:
case SerializedPropertyType.Vector4:
case SerializedPropertyType.Quaternion:
return true;
default:
return false;
}
}
但是,似乎场景参考已注册为可扩展属性,即使未注册。 这是因为-apparently- Unity将其注册为Generic
类型。
我可以通过将SerializedProperty.propertyType
设置为更有意义的类型来解决此问题,但是它是只读的。
因此,如何设置自定义属性抽屉的SerializedProperty.propertyType
?
它没有记录,但是Generic
类型自动为任何自定义类分配(例如SceneReference
)。 您不能更改propertyType
因为它是只读的 ...并且您不能告诉编译器将自定义类作为其他类型来处理...
即使你可以......这将是一个“更有意义的类型”? SerializedPropertyType
的可用类型是有限的,并且它们对于自定义类都没有更有意义的意义。
这里的主要“问题”是:
SerializableDictionary
抽屉简单地假定,如果您有一个没有自定义PropertyDrawer
的自定义( Generic
)类-因此使用默认抽屉-它的行为与Quaternion
或Vector4
的默认抽屉完全一样:
由于SceneReference
的抽屉没有实现此行为,因此将其绘制在字典的键字段顶部。
因此,作为最简单的修复程序,您只需删除
case SerializedPropertyType.Generic:
因此,将SceneAsset
(以及所有其他自定义类 )视为正常的展开字段- SceneAsset
品味
另外,您可以做的是更改SceneReference
的PropertyDrawer
以反映例如Quaternion
的行为:
property.isExpaned
值的标签的EditorGUI.Foldout
if(!property.isExpanded)
的条件上添加一行 可能看起来像:
// Made these two const btw
private const float PAD_SIZE = 2f;
private const float FOOTER_HEIGHT = 10f;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Move this up
EditorGUI.BeginProperty(position, GUIContent.none, property);
{
// Here we add the foldout using a single line height, the label and change
// the value of property.isExpanded
property.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, lineHeight), property.isExpanded, label);
// Now you want to draw the content only if you unfold this property
if (property.isExpanded)
{
// Optional: Indent the content
//EditorGUI.indentLevel++;
//{
// reduce the height by one line and move the content one line below
position.height -= lineHeight;
position.y += lineHeight;
var sceneAssetProperty = GetSceneAssetProperty(property);
// Draw the Box Background
position.height -= FOOTER_HEIGHT;
GUI.Box(EditorGUI.IndentedRect(position), GUIContent.none, EditorStyles.helpBox);
position = boxPadding.Remove(position);
position.height = lineHeight;
// Draw the main Object field
label.tooltip = "The actual Scene Asset reference.\nOn serialize this is also stored as the asset's path.";
var sceneControlID = GUIUtility.GetControlID(FocusType.Passive);
EditorGUI.BeginChangeCheck();
{
// removed the label here since we already have it in the foldout before
sceneAssetProperty.objectReferenceValue = EditorGUI.ObjectField(position, sceneAssetProperty.objectReferenceValue, typeof(SceneAsset), false);
}
var buildScene = BuildUtils.GetBuildScene(sceneAssetProperty.objectReferenceValue);
if (EditorGUI.EndChangeCheck())
{
// If no valid scene asset was selected, reset the stored path accordingly
if (buildScene.scene == null) GetScenePathProperty(property).stringValue = string.Empty;
}
position.y += paddedLine;
if (!buildScene.assetGUID.Empty())
{
// Draw the Build Settings Info of the selected Scene
DrawSceneInfoGUI(position, buildScene, sceneControlID + 1);
}
// Optional: If enabled before reset the indentlevel
//}
//EditorGUI.indentLevel--;
}
}
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var sceneAssetProperty = GetSceneAssetProperty(property);
// Add an additional line and check if property.isExpanded
var lines = property.isExpanded ? sceneAssetProperty.objectReferenceValue != null ? 3 : 2 : 1;
// If this oneliner is confusing you - it does the same as
//var line = 3; // Fully expanded and with info
//if(sceneAssetProperty.objectReferenceValue == null) line = 2;
//if(!property.isExpanded) line = 1;
return boxPadding.vertical + lineHeight * lines + PAD_SIZE * (lines - 1) + FOOTER_HEIGHT;
}
现在看起来像
[Serializable]
public class TestDict : SerializableDictionary<string, SceneReference> { }
public class Example : MonoBehaviour
{
public SceneReference NormalReference;
public TestDict DictExample = new TestDict();
}
想像这样的课程
public class Test
{
public string stringProperty;
}
现在,尝试设置propertyType基本上就像是试图告诉编译器更改类的属性类型,这是不可能的,因为它已被记录为“字符串”。
你能做的是
static bool CanPropertyBeExpanded(SerializedProperty property)
{
float height = EditorGUI.GetPropertyHeight(property);
// Property expandable if its height is twice the single line height.
return height >= EditorGUIUtility.singleLineHeight * 2;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.