gpt4 book ai didi

c# - 如何在 CustomPropertyDrawer 中设置 SerializedProperty.propertyType

转载 作者:太空宇宙 更新时间:2023-11-03 22:30:47 28 4
gpt4 key购买 nike

我正在使用这两个库:

基本上,可序列化字典通过以下检查查看 propertyType 以确定属性是否可以扩展:

static bool CanPropertyBeExpanded(SerializedProperty property)
{
switch(property.propertyType)
{
case SerializedPropertyType.Generic:
case SerializedPropertyType.Vector4:
case SerializedPropertyType.Quaternion:
return true;
default:
return false;
}
}

但是,场景引用似乎已注册为可扩展属性,尽管它不是。这是因为 - 显然 - Unity 将其注册为 Generic 类型。

我可以通过将 SerializedProperty.propertyType 设置为更有意义的类型来简单地解决这个问题,但它是只读的。

那么,如何设置自定义属性抽屉的 SerializedProperty.propertyType

最佳答案

它没有记录,但类型 Generic 会自动分配给任何自定义类(例如 SceneReference)。您不能更改propertyType,因为它是只读 ...并且您不能告诉编译器将您的自定义类处理为别的……

即使如果您可以……什么是“更有意义的类型”? SerializedPropertyType 的可用类型是有限的,没有一个对自定义类更有意义。


这里的主要“问题”是:

SerializableDictionary 抽屉简单地假设通常如果你有一个没有自定义 PropertyDrawer 的自定义(Generic)类 - 所以使用默认抽屉- 它的行为与 QuaternionVector4 的默认抽屉完全一样:

enter image description here

  • 第一行有标签和折页
  • 字段/内容在下面绘制,并且仅当属性被折叠时

由于 SceneReference 的抽屉未实现此行为,因此它被绘制在字典的键字段之上。


所以作为最简单的修复当然你可以简单地删除

case SerializedPropertyType.Generic:

因此 SceneAsset(和所有其他自定义类)被视为正常展开的字段 - 品味问题

enter image description here


或者,您可以更改 SceneReferencePropertyDrawer 以反射(reflect)例如四元数:

  • 添加一个 EditorGUI.Foldout 带有改变 property.isExpaned 值的标签
  • 将任何内容移到下方一行(可选)
  • 将一行添加到属性高度和 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();
}

enter image description here


关于c# - 如何在 CustomPropertyDrawer 中设置 SerializedProperty.propertyType,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57948014/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com