C# 如何使用bool在Unity inspector中启用/禁用列表?
我有一个名为C# 如何使用bool在Unity inspector中启用/禁用列表?,c#,unity3d,unity-editor,C#,Unity3d,Unity Editor,我有一个名为Level的ScriptableObject脚本,在Level脚本中我有一个游戏对象列表和一个名为introductenewenemies的bool变量 我想做的是:我想在bool变量打开时启用游戏对象列表,在关闭时使用Unity自定义检查器方法或属性抽屉隐藏/灰显(我们无法向其添加元素)。有那么难吗?要隐藏变量,请查看 但如果您想灰显一个字段,您可以这样做。最好的方法是自定义属性。我将从显示最终结果开始: 使用字段隐藏/显示其他字段: public bool showHideLi
Level
的ScriptableObject
脚本,在Level脚本中我有一个游戏对象列表和一个名为introductenewenemies
的bool变量
我想做的是:我想在bool变量打开时启用游戏对象列表,在关闭时使用Unity自定义检查器方法或属性抽屉隐藏/灰显(我们无法向其添加元素)。有那么难吗?要隐藏变量,请查看
但如果您想灰显一个字段,您可以这样做。最好的方法是自定义属性。我将从显示最终结果开始:
- 使用字段隐藏/显示其他字段:
public bool showHideList = false; [ShowIf(ActionOnConditionFail.DontDraw, ConditionOperator.And, nameof(showHideList))] public string aField = "item 1";
public bool enableDisableList = false; [ShowIf(ActionOnConditionFail.JustDisable, ConditionOperator.And, nameof(enableDisableList))] public string anotherField = "item 2";
- 使用一个字段启用/禁用另一个字段:
public bool showHideList = false; [ShowIf(ActionOnConditionFail.DontDraw, ConditionOperator.And, nameof(showHideList))] public string aField = "item 1";
public bool enableDisableList = false; [ShowIf(ActionOnConditionFail.JustDisable, ConditionOperator.And, nameof(enableDisableList))] public string anotherField = "item 2";
- 使用方法获取条件值:
[ShowIf(ActionOnConditionFail.JustDisable, ConditionOperator.And,nameof(CalculateIsEnabled))] public string yetAnotherField = "one more"; public bool CalculateIsEnabled() { return true; }
- 在同一字段上使用多个条件:
public bool condition1; public bool condition2; [ShowIf(ActionOnConditionFail.JustDisable, ConditionOperator.And, nameof(condition1), nameof(condition2))] public string oneLastField= "last field";
是怎么做到的?
public enum ConditionOperator
{
// A field is visible/enabled only if all conditions are true.
And,
// A field is visible/enabled if at least ONE condition is true.
Or,
}
public enum ActionOnConditionFail
{
// If condition(s) are false, don't draw the field at all.
DontDraw,
// If condition(s) are false, just set the field as disabled.
JustDisable,
}
using System;
using UnityEngine;
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class ShowIfAttribute : PropertyAttribute
{
public ActionOnConditionFail Action {get;private set;}
public ConditionOperator Operator {get;private set;}
public string[] Conditions {get;private set;}
public ShowIfAttribute(ActionOnConditionFail action, ConditionOperator conditionOperator, params string[] conditions)
{
Action = action;
Operator = conditionOperator;
Conditions = conditions;
}
}
ShowIfAttribute
处理字段的重要部分,此抽屉脚本需要位于任何“编辑器”文件夹下:
using System.Reflection;
using UnityEditor;
using System.Collections.Generic;
using System;
using System.Linq;
using UnityEngine;
[CustomPropertyDrawer(typeof(ShowIfAttribute), true)]
public class ShowIfAttributeDrawer : PropertyDrawer
{
#region Reflection helpers.
private static MethodInfo GetMethod(object target, string methodName)
{
return GetAllMethods(target, m => m.Name.Equals(methodName,
StringComparison.InvariantCulture)).FirstOrDefault();
}
private static FieldInfo GetField(object target, string fieldName)
{
return GetAllFields(target, f => f.Name.Equals(fieldName,
StringComparison.InvariantCulture)).FirstOrDefault();
}
private static IEnumerable<FieldInfo> GetAllFields(object target, Func<FieldInfo,
bool> predicate)
{
List<Type> types = new List<Type>()
{
target.GetType()
};
while (types.Last().BaseType != null)
{
types.Add(types.Last().BaseType);
}
for (int i = types.Count - 1; i >= 0; i--)
{
IEnumerable<FieldInfo> fieldInfos = types[i]
.GetFields(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(predicate);
foreach (var fieldInfo in fieldInfos)
{
yield return fieldInfo;
}
}
}
private static IEnumerable<MethodInfo> GetAllMethods(object target,
Func<MethodInfo, bool> predicate)
{
IEnumerable<MethodInfo> methodInfos = target.GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public)
.Where(predicate);
return methodInfos;
}
#endregion
private bool MeetsConditions(SerializedProperty property)
{
var showIfAttribute = this.attribute as ShowIfAttribute;
var target = property.serializedObject.targetObject;
List<bool> conditionValues = new List<bool>();
foreach (var condition in showIfAttribute.Conditions)
{
FieldInfo conditionField = GetField(target, condition);
if (conditionField != null &&
conditionField.FieldType == typeof(bool))
{
conditionValues.Add((bool)conditionField.GetValue(target));
}
MethodInfo conditionMethod = GetMethod(target, condition);
if (conditionMethod != null &&
conditionMethod.ReturnType == typeof(bool) &&
conditionMethod.GetParameters().Length == 0)
{
conditionValues.Add((bool)conditionMethod.Invoke(target, null));
}
}
if (conditionValues.Count > 0)
{
bool met;
if (showIfAttribute.Operator == ConditionOperator.And)
{
met = true;
foreach (var value in conditionValues)
{
met = met && value;
}
}
else
{
met = false;
foreach (var value in conditionValues)
{
met = met || value;
}
}
return met;
}
else
{
Debug.LogError("Invalid boolean condition fields or methods used!");
return true;
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent
label)
{
// Calcluate the property height, if we don't meet the condition and the draw
mode is DontDraw, then height will be 0.
bool meetsCondition = MeetsConditions(property);
var showIfAttribute = this.attribute as ShowIfAttribute;
if (!meetsCondition && showIfAttribute.Action ==
ActionOnConditionFail.DontDraw)
return 0;
return base.GetPropertyHeight(property, label);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent
label)
{
bool meetsCondition = MeetsConditions(property);
// Early out, if conditions met, draw and go.
if (meetsCondition)
{
EditorGUI.PropertyField(position, property, label, true);
return;
}
var showIfAttribute = this.attribute as ShowIfAttribute;
if(showIfAttribute.Action == ActionOnConditionFail.DontDraw)
{
return;
}
else if (showIfAttribute.Action == ActionOnConditionFail.JustDisable)
{
EditorGUI.BeginDisabledGroup(true);
EditorGUI.PropertyField(position, property, label, true);
EditorGUI.EndDisabledGroup();
}
}
}
使用系统反射;
使用UnityEditor;
使用System.Collections.Generic;
使用制度;
使用System.Linq;
使用UnityEngine;
[CustomPropertyDrawer(typeof(ShowIfAttribute),true)]
公共类ShowIfAttributedDrawer:PropertyDrawer
{
#区域反射助手。
私有静态MethodInfo GetMethod(对象目标,字符串methodName)
{
返回GetAllMethods(target,m=>m.Name.Equals(methodName,
StringComparison.InvariantCulture().FirstOrDefault();
}
私有静态FieldInfo GetField(对象目标,字符串fieldName)
{
返回GetAllFields(target,f=>f.Name.Equals(fieldName,
StringComparison.InvariantCulture().FirstOrDefault();
}
私有静态IEnumerable GetAllFields(对象目标,Func谓词)
{
列表类型=新列表()
{
target.GetType()
};
while(types.Last().BaseType!=null)
{
添加(types.Last().BaseType);
}
对于(int i=types.Count-1;i>=0;i--)
{
IEnumerable fieldInfos=类型[i]
.GetFields(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(谓语);
foreach(fieldInfo中的var fieldInfo)
{
收益率返回字段信息;
}
}
}
私有静态IEnumerable GetAllMethods(对象目标,
Func谓词)
{
IEnumerable methodInfos=target.GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public)
.Where(谓语);
返回方法信息;
}
#端区
私有bool MEETSCONDECTIONS(私有财产)
{
var showIfAttribute=this.attribute作为showIfAttribute;
var target=property.serializedObject.targetObject;
列表条件值=新列表();
foreach(ShowiAttribute.Conditions中的var条件)
{
FieldInfo conditionField=GetField(目标、条件);
if(conditionField!=null&&
conditionField.FieldType==typeof(bool))
{
添加((bool)conditionField.GetValue(target));
}
MethodInfo conditionMethod=GetMethod(目标、条件);
if(conditionMethod!=null&&
conditionMethod.ReturnType==typeof(bool)&&
conditionMethod.GetParameters().Length==0)
{
添加((bool)conditionMethod.Invoke(target,null));
}
}
如果(conditionValues.Count>0)
{
布尔梅特;
if(showIfAttribute.Operator==ConditionOperator.And)
{
met=真;
foreach(条件值中的var值)
{
满足=满足和价值;
}
}
其他的
{
met=假;
foreach(条件值中的var值)
{
met=met | |值;
}
}
回程会议;
}
其他的
{
LogError(“使用的布尔条件字段或方法无效!”);
返回true;
}
}
公共覆盖浮点GetPropertyHight(SerializedProperty属性,GUIContent
标签)
{
//如果我们不符合条件和图纸,则计算属性高度
模式为DontDraw,则高度为0。
布尔MeetCondition=MeetConditions(属性);
var showIfAttribute=this.attribute作为showIfAttribute;
如果(!MeetCondition&&showIfAttribute.Action==
ActionOnConditionFail.DontDraw)
返回0;
返回base.GetPropertyHeight(属性,标签);
}
public override void OnGUI(Rect位置、SerializedProperty属性、GUIContent
标签)
{
布尔MeetCondition=MeetConditions(属性);
//提前退出,如果条件满足,抽签离开。
如果(满足条件)
{
EditorGUI.PropertyField(位置、属性、标签、true);
返回;
}
var showIfAttribute=this.attribute作为showIfAttribute;
if(showIfAttribute.Action==ActionOnConditionFail.DontDraw)
{
返回;
}
else if(showIfAttribute.Action==ActionOnConditionFail.JustDisable)