Odin特性解析
- 一、前言
- 二、特性大全
-
- 2.1 限制相关
- 2.2 通用特性
-
- 2.2.1 【ShowInInspector】显示在Inspector面板
- 2.2.2 【OnValueChanged】值变化回调
- 2.2.3 【Delayed】&【DelayedProperty】延迟
- 2.2.4 【GUIColor】变色
- 2.2.4 【ColorPalette】颜色调色板
- 2.2.5 【Title】& 【HideLabel】增加标题&隐藏字段名
- 2.2.6 【DisplayAsString】显示内容
- 2.2.7 【PropertyOrder】字段优先级
- 2.2.7 【PropertySpace】字段间隔
- 2.2.8 【Searchable】查找
- 2.2.9 【MultiLineProperty】多行输入框
- 2.2.10 【EnumPaging】枚举分页
- 2.2.11 【EnumToggleButtons】枚举下拉框转水平布局
- 2.2.12 【SuffixLabel】Label增加后缀
- 2.2.13 【InlineButton】在末尾增加按钮
- 2.2.14 【LabelText】重命名
- 2.3 较特殊的特性
- 2.4 Group 组
- 2.5 Collections 收集器
- 2.6 Conditionals 条件
- 三、窗口
一、前言
Odin是Unity里一款非常强大的编辑器插件,它提供了很多丰富的特性(Attribute),可以用来丰富编辑器的显示和交互。下面列举一些好用的特性。
二、特性大全
2.1 限制相关
2.1.1 【AssetsOnly】仅Project资源
- 功能:
限制仅可选择Project下的资源,Scene下的不能选 - 示例:
[AssetsOnly]
public GameObject SomePrefab;
2.1.2 【SceneObjectsOnly】仅Scene资源
- 功能:
限制仅可选择Scene下的资源,Project下的不能选 - 示例:
[SceneObjectsOnly]
public GameObject SomePrefab;
2.1.3 【MinValue】&【MaxValue】最小值&最大值
- 功能:
限制最小指和最大值 - 示例:
[MinValue(0)] [MaxValue(5)]
public int val;
2.1.4 【MinMaxSlider】最小最大滑动条(修饰Vector2)
- 功能:
也是限制最小值和最大值,但有一个滚动条。用于修饰Vector2 - 示例:
[MinMaxSlider(-10, 10)]
public Vector2 MinMaxValueSlider = new Vector2(-7, -2); - 效果图:
2.1.5 【Range】&【PropertyRange】字段&属性范围
-
功能:
Range用来限制字段范围;
PropertyRange 更强大一点,还可以限制属性范围;正常Unity内置的功能是显示不了字段的,这里我们用了Odin里的【ShowInInspector】特性,来把Property 属性显示出来 -
示例:
[Range(0, 10)]
public int Field = 2;[ShowInInspector,PropertyRange(0, 10)]
public int Property { get; set; } -
效果图:
-
进阶用法:
我们上面的最小最大值都是固定值,其实还可以用动态的字段值来作范围,如下面的例子 -
进阶示例:
[PropertyRange(0, “Max”)]
public int Dynamic = 6;public int Max = 100;
2.1.6 【Required】限制资源不能空
-
功能:
Required可以用来限制一个资源不能为空 -
语法:
[Required(“当资源为空时的提示,可不填”)] -
示例:
[Required]
public GameObject MyGameObject;[Required(“Custom error message.”)]
public Rigidbody MyRigidbody; -
效果图:
2.1.7 【ValidateInput】赋值验证
-
功能:
ValidateInput是个很实用的功能,当用户对字段赋值后,会触发回调方法。然后我们可以写代码逻辑来对用户赋值的实体进行检查。如果检查不通过,可以给予提示 -
语法:
[ValidateInput(“回调方法名”, “默认提示”)] -
示例
[ValidateInput("HasMeshRendererDynamicMessageAndType", "Prefab must have a MeshRenderer component")]
public GameObject DynamicMessageAndType;
//返回类型为bool,表示是否通过检测
private bool HasMeshRendererDynamicMessageAndType(GameObject gameObject, ref string errorMessage, ref InfoMessageType? messageType)
{
//没有赋值时,通过检测
if (gameObject == null) return true;
//如果赋值的GameObject没有MeshRenderer,return false检测不通过
if (gameObject.GetComponentInChildren<MeshRenderer>() == null)
{
// 设置提示信息
errorMessage = "\"" + gameObject.name + "\" should have a MeshRenderer component";
// //设置警告类型
messageType = InfoMessageType.Warning;
return false;
}
return true;
}
2.1.8 【TypeFilter】限制类型
- 功能:
TypeFilter 可以用来限制只能选择指定的类型集合 - 示例
[ShowInInspector]
[TypeFilter("GetFilteredTypeList")]
public BaseClass A, B;
[ShowInInspector]
[TypeFilter("GetFilteredTypeList")]
public BaseClass[] Array = new BaseClass[3];
public IEnumerable<Type> GetFilteredTypeList()
{
var q = typeof(BaseClass).Assembly.GetTypes()
.Where(x => !x.IsAbstract) // 排除 BaseClass
.Where(x => !x.IsGenericTypeDefinition) // 排除 泛型,如C1<>
.Where(x => typeof(BaseClass).IsAssignableFrom(x)); // 排除没有继承BaseClass的类型
// 增加特定的类
q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(GameObject)));
q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(AnimationCurve)));
q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(List<float>)));
return q;
}
public abstract class BaseClass
{
public int BaseField;
}
public class A1 : BaseClass { public int _A1; }
public class A2 : A1 { public int _A2; }
public class A3 : A2 { public int _A3; }
public class B1 : BaseClass { public int _B1; }
public class B2 : B1 { public int _B2; }
public class B3 : B2 { public int _B3; }
public class C1<T> : BaseClass { public T C; }
- 效果图
2.1.9 【ReadOnly】只读
-
功能:
ReadOnly 可以让显示在面板上的属性不能修改 -
示例:
[ReadOnly]
public string MyString = “This is displayed as text”;[ReadOnly]
public int MyInt = 9001;[ReadOnly]
public int[] MyIntList = new int[] { 1, 2, 3, 4, 5, 6, 7, }; -
效果图:
2.2 通用特性
这里列举一些实用但不好归类的特性
2.2.1 【ShowInInspector】显示在Inspector面板
-
功能:
ShowInInspector 可以让属性,静态变量等平常不能再Inspector显示的字段显示在面板。挺使用的一个功能 -
示例:
[ShowInInspector]
public string DelayedProperty { get; set; }[ShowInInspector]
public static string testStr; -
效果图:
2.2.2 【OnValueChanged】值变化回调
-
功能:
OnValueChanged 可以在字段的值变化后,调用回调方法 -
语法:
[OnValueChanged(“回调方法名”)] -
示例:
[OnValueChanged(“OnValueChanged”)]
public int val;private void OnValueChanged()
{
Debug.Log(“Value changed!”);
} -
效果图:
2.2.3 【Delayed】&【DelayedProperty】延迟
-
功能:
Delayed 和 DelayedProperty 可以搭配上面的OnValueChanged使用,OnValueChanged能在值变化后回调,但每次变化都会回调,比如稍微拖拉一下值,你看上面的打印,回调了174次。这时Delayed 就派上用场了,可以在值变化完成后才回调,就不会有那么多回调了。Delayed 修饰通常字段,DelayedProperty 可以用来修饰属性 -
示例:
[Delayed]
[OnValueChanged(“OnValueChanged”)]
public int DelayedField;[ShowInInspector, DelayedProperty]
[OnValueChanged(“OnValueChanged”)]
public string DelayedProperty { get; set; }private void OnValueChanged()
{
Debug.Log(“Value changed!”);
} -
效果图:
2.2.4 【GUIColor】变色
- 功能:
GUIColor 可以让字段变色,也可以让按钮变色,还能颜色渐变。接下来我们看下官方给的示例 - 示例:
[GUIColor(0.3f, 0.8f, 0.8f, 1f)]
public int ColoredInt1;
[GUIColor(0.3f, 0.8f, 0.8f, 1f)]
public int ColoredInt2;
[ButtonGroup]
[GUIColor(0, 1, 0)]
private void Apply()
{
}
[ButtonGroup]
[GUIColor(1, 0.6f, 0.4f)]
private void Cancel()
{
}
[InfoBox("You can also reference a color member to dynamically change the color of a property.")]
[GUIColor("GetButtonColor")]
[Button("I Am Fabulous", ButtonSizes.Gigantic)]
private static void IAmFabulous()
{
}
[Button(ButtonSizes.Large)]
[GUIColor("@Color.Lerp(Color.red, Color.green, Mathf.Abs(Mathf.Sin((float)EditorApplication.timeSinceStartup)))")]
private static void Expressive()
{
}
private static Color GetButtonColor()
{
Sirenix.Utilities.Editor.GUIHelper.RequestRepaint();
return Color.HSVToRGB(Mathf.Cos((float)UnityEditor.EditorAp