请选择 进入手机版 | 继续访问电脑版

查看: 21892|回复: 130

[原创] 在Unity 5中如何控制检视面板上的属性是否显示?

  [复制链接]

1012

主题

1694

帖子

2万

贡献

管理员

Rank: 9Rank: 9Rank: 9

积分
21960
QQ
发表于 2016-5-13 08:46:53 | 显示全部楼层 |阅读模式
01.jpg

当脚本中有大量属性或字段需要在检视面板中调整时,检视面板会变得杂乱无章。有没有什么办法可以自己来管理这些属性是否显示呢?本文就为大家介绍无需自定义检视面板来管理属性显示的方法。

首先介绍HeaderAttributes的用法,让大家对控制检视面板属性有个概念。然后介绍如果通过脚本中的bool变量来控制检视面板上属性的显隐。

改善可读性
看看下面的检视面板示例。

02.jpg

即便是这样一个简单的脚本在检视面板上看起来已经不太好理解了。

对属性进行分组可以方便设计师们理解脚本的作用。也要能清楚区分脚本中不同函数的不同变量。这可以通过 HeaderAttributes来实现。

HeaderAttribute示例
[C#] 纯文本查看 复制代码
[Header("Auto Aim")]
public bool EnableAutoAim = false;

03.jpg

Unity提供了一系列的属性来帮助管理脚本在检视面板上的显示以及用户交互。并不需为各脚本单独自定义检视面板。

一些实用且常用的属性都位于SpaceAttribute、TooltipAttribute、RangeAttribute内。

根据用户输入控制字段显隐
有了分组,下面就来实现用变量控制变量显隐。这里Auto Anim分类下的属性只有在EnableAutoAim被设为True时才会显示。

首先当EnableAutoAim被设为False时,将所有与EnableAutoAim关联的属性禁用。

04.jpg

实现这一步需要自定义属性并使用PropertyDrawer。具体细节可查看教程。
https://unity3d.com/learn/tutori ... s-custom-inspectors

下面来介绍实现逻辑以及对PropertyDrawer和属性的设置。

第一步:创建脚本
首先创建两个脚本ConditionalHideAttribute和ConditionalHidePropertyDrawer。

注意要将ConditionalHidePropertyDrawer脚本放在Editor文件夹下,负责会访问不到需要的属性。ConditionalHideAttribute脚本则放在外面。

05.jpg

第二步:ConditionalHideAttribute
首先创建属性,然后定义bool字段来控制检视面板上属性的显示或隐藏,并且可以进行切换。

ConditionalHideAttribute继承自PropertyAttribute类,只包含构造函数和一些数据。该类的主要目的是提供在PropertyDrawer内使用的额外数据。如果想添加另外的选项或参数也可在此添加。

ConditionalHideAttribute类最上方的AttributeUsage属性用于控制是否可以使用ConditionalHideAttribute属性。

[C#] 纯文本查看 复制代码
using UnityEngine;
using System;
using System.Collections;
 
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property |
    AttributeTargets.Class | AttributeTargets.Struct, Inherited = true)]
public class ConditionalHideAttribute : PropertyAttribute
{
    //The name of the bool field that will be in control
    public string ConditionalSourceField = "";
    //TRUE = Hide in inspector / FALSE = Disable in inspector 
    public bool HideInInspector = false;
 
    public ConditionalHideAttribute(string conditionalSourceField)
    {
        this.ConditionalSourceField = conditionalSourceField;
        this.HideInInspector = false;
    }
 
    public ConditionalHideAttribute(string conditionalSourceField, bool hideInInspector)
    {
        this.ConditionalSourceField = conditionalSourceField;
        this.HideInInspector = hideInInspector;
    }
}


第三步:ConditionalHidePropertyDrawer
对于PropertyDrawer还有些事要做:
        如果想让Unity在检视面板上绘制字段,需要:
                检查自定义属性中的参数
                隐藏或禁用基于属性参数绘制的字段
[C#] 纯文本查看 复制代码
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  {
      //get the attribute data
      ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute;
      //check if the propery we want to draw should be enabled
      bool enabled = GetConditionalHideAttributeResult(condHAtt, property);
 
      //Enable/disable the property
      bool wasEnabled = GUI.enabled;
      GUI.enabled = enabled;
 
      //Check if we should draw the property
      if (!condHAtt.HideInInspector || enabled)
      {
          EditorGUI.PropertyField(position, property, label, true);
      }
 
      //Ensure that the next property that is being drawn uses the correct settings
      GUI.enabled = wasEnabled;
  }

调用GetConditionalHideAttributeResult函数来检查字段是否应该显示。
[C#] 纯文本查看 复制代码
private bool GetConditionalHideAttributeResult(ConditionalHideAttribute condHAtt, SerializedProperty property)
{
    bool enabled = true;
    //Look for the sourcefield within the object that the property belongs to
    SerializedProperty sourcePropertyValue = property.serializedObject.FindProperty(condHAtt.ConditionalSourceField);
    if (sourcePropertyValue != null)
    {
        enabled = sourcePropertyValue.boolValue;
    }
    else
    {
        Debug.LogWarning("Attempting to use a ConditionalHideAttribute but no matching SourcePropertyValue found in object: " + condHAtt.ConditionalSourceField);
    }
 
    return enabled;
}


如果是需要隐藏的字段,计算字段高度让后面的字段不会被重叠绘制        
[C#] 纯文本查看 复制代码
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
  {
      ConditionalHideAttribute condHAtt = (ConditionalHideAttribute)attribute;
      bool enabled = GetConditionalHideAttributeResult(condHAtt, property);
 
      if (!condHAtt.HideInInspector || enabled)
      {
          return EditorGUI.GetPropertyHeight(property, label);
      }
      else
      {
          //The property is not being drawn
          //We want to undo the spacing added before and after the property
          return -EditorGUIUtility.standardVerticalSpacing;
      }
  }
        
完整的ConditionalHidePropertyDrawer脚本代码如下:
请回复该贴,获取完整代码。

游客,如果您要查看本帖隐藏内容请回复


第四步:使用
使用属性ConditionalHideAttribute就像使用HeaderAttribute一样简单方便。

用法:
[C#] 纯文本查看 复制代码
[Header("Auto Aim")]
public bool EnableAutoAim = false;
 
[ConditionalHide("EnableAutoAim", true)]
public float Range = 0.0f;
[ConditionalHide("EnableAutoAim", true)]
public bool AimAtClosestTarget = true; 
[ConditionalHide("EnableAutoAim", true)]
public DemoClass ExampleDataClass = new DemoClass();
[ConditionalHide("EnableAutoAim", true)]
public AnimationCurve AimOffsetCurve = new AnimationCurve();


将第二个参数留空或设为False即可使用Enable或Disable方法来绘制属性。

用法:
[C#] 纯文本查看 复制代码
[Header("Resources")]
public bool ConsumeResources = true;
 
[ConditionalHide("ConsumeResources")]
public bool DestroyOnResourcesDepleted = true;
[ConditionalHide("ConsumeResources")]
public float ResourceAmount = 100.0f;
[ConditionalHide("ConsumeResources")]
public DemoClass AnotherExampleDataClass = new DemoClass();


注意事项
有些情况下该属性会失效。

第一种是列表和数组。这种情况下属性绘制器(Property Drawer)将应用于列表的内容而非列表本身。仍然可以设置列表元素个数。

但如果该列表位于可序列化类中,就不会存在这个问题。

06.jpg

另一种会导致属性失效的情况是混合使用了其它属性绘制器(Property Drawer)例如TextAreaAttribute时,会改变属性本身的绘制方式。

这是因为类似TextAreaAttribute这样的属性会调用自己的OnGUI进行绘制,计算高度也是调用自己的GetPropertyHeight函数。这种情况下最后被调用的属性会决定最终绘制的内容。

扩展
还可以支持两个bool参数,只需加入另一个ConditionalSourceField作为参数即可。
用法:
[C#] 纯文本查看 复制代码
[ConditionalHide("Condition01", ConditionalSourceField2 = “Condition02")]

另外还能支持将对象引用作为判断条件。你也可以自己扩展代码添加一些条件判断如整数、浮点数或字符串等等。

原文链接:http://www.brechtos.com/hiding-o ... ers-within-unity-5/
感谢Unity官方中文社区翻译组成员:“小七不乖” 对本文翻译所做的贡献。
转载请注明来源:Unity官方中文社区 (forum.china.unity3d.com)。请勿私自更改任何版权说明信息。

0

主题

2

帖子

35

贡献

初级UU族—1级

Rank: 1

积分
35
发表于 2016-5-14 03:58:26 | 显示全部楼层
非常好

0

主题

1

帖子

10

贡献

初级UU族—1级

Rank: 1

积分
10
发表于 2016-5-15 03:35:08 | 显示全部楼层
feichanghao

0

主题

20

帖子

340

贡献

初级UU族—3级

Rank: 3Rank: 3

积分
340
发表于 2016-5-15 09:03:51 | 显示全部楼层
6666666666666666666666

0

主题

2

帖子

25

贡献

初级UU族—1级

Rank: 1

积分
25
发表于 2016-5-16 05:42:42 | 显示全部楼层
1111111111111111111111111111111111111111111111111

0

主题

6

帖子

105

贡献

初级UU族—2级

Rank: 2

积分
105
发表于 2016-5-16 07:11:53 | 显示全部楼层
er ewr ewr e

1

主题

8

帖子

75

贡献

初级UU族—2级

Rank: 2

积分
75
发表于 2016-5-19 02:40:13 | 显示全部楼层
感谢分享,好好学习一下

0

主题

1

帖子

110

贡献

初级UU族—2级

Rank: 2

积分
110
发表于 2016-5-20 01:22:17 | 显示全部楼层
真的是很好的东西,希望多分享干货,多谢大神

0

主题

1

帖子

30

贡献

初级UU族—1级

Rank: 1

积分
30
发表于 2016-5-23 05:06:31 | 显示全部楼层
在Unity 5中如何控制检视面板上的属性是否显示

0

主题

1

帖子

10

贡献

初级UU族—1级

Rank: 1

积分
10
发表于 2016-5-30 07:03:40 | 显示全部楼层
学习了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表