- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用这两个库:
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;
}
}
但是,场景引用似乎已注册为可扩展属性,尽管它不是。这是因为 - 显然 - Unity 将其注册为 Generic
类型。
我可以通过将 SerializedProperty.propertyType
设置为更有意义的类型来简单地解决这个问题,但它是只读的。
那么,如何设置自定义属性抽屉的 SerializedProperty.propertyType
?
最佳答案
它没有记录,但类型 Generic
会自动分配给任何自定义类(例如 SceneReference
)。您不能更改propertyType
,因为它是只读 ...并且您不能告诉编译器将您的自定义类处理为别的……
即使如果您可以……什么是“更有意义的类型”? SerializedPropertyType
的可用类型是有限的,没有一个对自定义类更有意义。
这里的主要“问题”是:
SerializableDictionary
抽屉简单地假设通常如果你有一个没有自定义 PropertyDrawer
的自定义(Generic
)类 - 所以使用默认抽屉- 它的行为与 Quaternion
或 Vector4
的默认抽屉完全一样:
由于 SceneReference
的抽屉未实现此行为,因此它被绘制在字典的键字段之上。
所以作为最简单的修复当然你可以简单地删除
case SerializedPropertyType.Generic:
因此 SceneAsset
(和所有其他自定义类)被视为正常展开的字段 - 品味问题
或者,您可以更改 SceneReference
的 PropertyDrawer
以反射(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();
}
关于c# - 如何在 CustomPropertyDrawer 中设置 SerializedProperty.propertyType,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57948014/
我有这样的类型定义: type Blah = { fields: { value: string }[] } 我们在这里看到字段是一堆数组条目。我想通过 $PropertyT
我有这样的类型定义: type Blah = { fields: { value: string }[] } 我们在这里看到字段是一堆数组条目。我想通过 $PropertyT
我怎样才能让它工作? switch(property.PropertyType){ case typeof(Boolean): //doStuff break;
这个问题在这里已经有了答案: C#: Getting size of a value-type variable at runtime? (8 个答案) 关闭 9 年前。 我有一个函数可以确定记录值
我有以下用 EF 生成的类“schakeling”,表示数据库表“schakeling”。在数据库中,'id' 是主键,'plc_id' 是外键。 public partial class schak
我正在尝试通过反序列化 json 来创建属性的新实例字符串。调用JsonConvert.DeserializeObject(string)当我明确说明 T 的类型时有效: var foo = Json
我有一个通用函数,可以使用反射从 DataRow 创建对象。我正在使用此函数从 Access 数据库导入表: private static T CreateItemFromRow(DataRow ro
我想使用 PropertyType 返回的类型来创建类型化函数。我发现这个相似 using type returned by Type.GetType() in c#但这提到了如何创建一个列表,但没有
我有如下类: public class SampleClassToTest { public static Fake SomeMethod(string parameter) {
我的问题是:怎样才能使 PropertyInfo.GetValue(object, null); 转换为 PropertyType 的返回值,而不是返回对象。 我试过 Convert.ChangeTy
我正在使用这两个库: Unity-SerializableDictionary: https://github.com/starikcetin/Unity-SerializableDictionary
我想使用反射获取属性类型。这是我的代码 var properties = type.GetProperties(); foreach (var propertyInfo in properties)
我正在遍历对象并初始化该对象的所有属性。首先,对象的类型即类被放置在我的同一个项目中并且工作正常。现在,我将该类移到另一个项目中,但仍然使用 AssemblyName.Namespace.Class
我只需要显示名称在必填字段列表中的属性。 我正在尝试做这样的事情,但是 p.PropertyType.Name == x 不正确: Pricing pricing = new Pricing(); T
我只需要显示名称在必填字段列表中的属性。 我正在尝试做这样的事情,但是 p.PropertyType.Name == x 不正确: Pricing pricing = new Pricing(); T
我是一名优秀的程序员,十分优秀!