如何检查拖到检查器上的可编写脚本的对象是否正在实现接口?
How can I check if a scriptable object dragged onto inspector is implementing an interface or not?
对于我的统一项目,我正在尝试制作一个自定义 属性 抽屉,以使检查器接受仅实现我通过属性参数传递的接口的对象。我很高兴我圆满地完成了 MonoBehaviour 对象的任务。但是,我在对可编写脚本的对象应用类似方法时遇到了麻烦。我需要帮助。
这是我的 属性 抽屉代码。问题是 C# 不允许我使用“is”关键字进行类型检查。这是我试过的一些代码
if(temp_SO is requiredAttribute.requiredType) {}
if(temp_SO is T) {}
if(temp_SO.GetType().Equals(requiredAttribute.requiredType) {}
但都失败了...
但是,正如下面的代码所示,如果我将其硬编码为 if(temp_SO is interface_C)
那么它就可以工作。我找不到动态传递类型值的方法。因为 IDE 不断抛出“预期为常数值”错误。任何帮助将不胜感激。谢谢..
[CustomPropertyDrawer(typeof(SOInterfaceExposeAttribute))]
public class SOInterfaceExposeAttributeDrawer : PropertyDrawer
{
Type T;
public override void OnGUI ( Rect position , SerializedProperty property , GUIContent label )
{
if ( property . propertyType == SerializedPropertyType . ObjectReference )
{
var requiredAttribute = this . attribute as SOInterfaceExposeAttribute;
T = requiredAttribute . requiredType;
var lastValidRef = property . objectReferenceValue;
EditorGUI . BeginProperty(position , label , property);
ScriptableObject temp_SO = EditorGUI . ObjectField(position , label , property . objectReferenceValue , typeof(ScriptableObject) , true) as ScriptableObject;
// Finish drawing property field.
if ( temp_SO != null )
{
if ( temp_SO is Interface_C)
{
Debug . Log("interface component found");
property . objectReferenceValue = temp_SO as ScriptableObject;
}
else
{
Debug . Log("interface component NOT found");
property . objectReferenceValue = lastValidRef;
}
}
EditorGUI . EndProperty();
}
else
{
// If field is not reference, show error message.
// Save previous color and change GUI to red.
var previousColor = GUI . color;
GUI . color = Color . red;
// Display label with error message.
EditorGUI . LabelField(position , label , new GUIContent("Property is not a reference type"));
// Revert color change.
GUI . color = previousColor;
}
}
}
is
确实需要常量类型参数。
你试过的另一种方式
if(temp_SO.GetType().Equals(requiredAttribute.requiredType)
不会工作,因为这两种类型肯定 不 相等,因为一个实现了另一个 ;)
你或许可以使用 IsInstanceOfType
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
if (requiredAttribute.requiredType.IsInstanceOfType(temp_SO))
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
if (requiredAttribute.requiredType.IsAssignableFrom(temp_SO.GetType()))
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
另一种方法是使用 FindInterfaces
来比较是否有任何继承类型实现了接口类型
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
// Filter taken from the linked examples
if (temp_SO.GetType().FindInterfaces(new TypeFilter((type, criteria) => type.ToString() == criteria.ToString()), requiredAttribute.requiredType.Name()).Length > 0)
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
顺便说一句,您可以通过不经常检查它来提高效率,而是仅在引用更改时将其包装在
中
EditorGUI.BeginChangeCheck();
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
if(EditorGUI.EndChangeCheck())
{
...
}
对于我的统一项目,我正在尝试制作一个自定义 属性 抽屉,以使检查器接受仅实现我通过属性参数传递的接口的对象。我很高兴我圆满地完成了 MonoBehaviour 对象的任务。但是,我在对可编写脚本的对象应用类似方法时遇到了麻烦。我需要帮助。
这是我的 属性 抽屉代码。问题是 C# 不允许我使用“is”关键字进行类型检查。这是我试过的一些代码
if(temp_SO is requiredAttribute.requiredType) {}
if(temp_SO is T) {}
if(temp_SO.GetType().Equals(requiredAttribute.requiredType) {}
但都失败了...
但是,正如下面的代码所示,如果我将其硬编码为 if(temp_SO is interface_C)
那么它就可以工作。我找不到动态传递类型值的方法。因为 IDE 不断抛出“预期为常数值”错误。任何帮助将不胜感激。谢谢..
[CustomPropertyDrawer(typeof(SOInterfaceExposeAttribute))]
public class SOInterfaceExposeAttributeDrawer : PropertyDrawer
{
Type T;
public override void OnGUI ( Rect position , SerializedProperty property , GUIContent label )
{
if ( property . propertyType == SerializedPropertyType . ObjectReference )
{
var requiredAttribute = this . attribute as SOInterfaceExposeAttribute;
T = requiredAttribute . requiredType;
var lastValidRef = property . objectReferenceValue;
EditorGUI . BeginProperty(position , label , property);
ScriptableObject temp_SO = EditorGUI . ObjectField(position , label , property . objectReferenceValue , typeof(ScriptableObject) , true) as ScriptableObject;
// Finish drawing property field.
if ( temp_SO != null )
{
if ( temp_SO is Interface_C)
{
Debug . Log("interface component found");
property . objectReferenceValue = temp_SO as ScriptableObject;
}
else
{
Debug . Log("interface component NOT found");
property . objectReferenceValue = lastValidRef;
}
}
EditorGUI . EndProperty();
}
else
{
// If field is not reference, show error message.
// Save previous color and change GUI to red.
var previousColor = GUI . color;
GUI . color = Color . red;
// Display label with error message.
EditorGUI . LabelField(position , label , new GUIContent("Property is not a reference type"));
// Revert color change.
GUI . color = previousColor;
}
}
}
is
确实需要常量类型参数。
你试过的另一种方式
if(temp_SO.GetType().Equals(requiredAttribute.requiredType)
不会工作,因为这两种类型肯定 不 相等,因为一个实现了另一个 ;)
你或许可以使用 IsInstanceOfType
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
if (requiredAttribute.requiredType.IsInstanceOfType(temp_SO))
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
if (requiredAttribute.requiredType.IsAssignableFrom(temp_SO.GetType()))
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
另一种方法是使用 FindInterfaces
来比较是否有任何继承类型实现了接口类型
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
// Finish drawing property field.
if (temp_SO != null)
{
// Filter taken from the linked examples
if (temp_SO.GetType().FindInterfaces(new TypeFilter((type, criteria) => type.ToString() == criteria.ToString()), requiredAttribute.requiredType.Name()).Length > 0)
{
Debug.Log("interface component found");
property.objectReferenceValue = temp_SO;
}
else
{
Debug.Log("interface component NOT found");
property.objectReferenceValue = lastValidRef;
}
}
顺便说一句,您可以通过不经常检查它来提高效率,而是仅在引用更改时将其包装在
中EditorGUI.BeginChangeCheck();
var temp_SO = EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(ScriptableObject), true);
if(EditorGUI.EndChangeCheck())
{
...
}