文章目录
- 1 说明
- 2 验证特性
- 2.1 AssetsOnly / SceneObjectsOnly
- 2.2 ChildGameObjectsOnly
- 2.3 DisallowModificationsIn
- 2.4 FilePath
- 2.5 FolderPath
- 2.6 MaxValue / MinValue
- 2.7 MinMaxSlider
- 2.8 PropertyRange
- 2.9 Required
- 2.10 RequiredIn
- 2.11 RequiredListLength
- 2.12 ValidateInput
1 说明
本文介绍 Odin Inspector 插件中有关验证特性的使用方法。
2 验证特性
2.1 AssetsOnly / SceneObjectsOnly
使目标对象在 Inspector 窗口中只能关联资源 / 场景对象,限制拖拽的资源类型。
// SceneAndAssetsOnlyExamplesComponent.cs
using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;
public class SceneAndAssetsOnlyExamplesComponent : MonoBehaviour
{
[Title("Assets only")]
[AssetsOnly]
public List<GameObject> OnlyPrefabs;
[AssetsOnly]
public GameObject SomePrefab;
[AssetsOnly]
public Material MaterialAsset;
[AssetsOnly]
public MeshRenderer SomeMeshRendererOnPrefab;
[Title("Scene Objects only")]
[SceneObjectsOnly]
public List<GameObject> OnlySceneObjects;
[SceneObjectsOnly]
public GameObject SomeSceneObject;
[SceneObjectsOnly]
public MeshRenderer SomeMeshRenderer;
}
2.2 ChildGameObjectsOnly
可用于 Components 和 GameObject,并在对象旁添加小按钮,点击按钮将显示其子物体中所有满足条件的对象。
IncludeSelf = true
是否包含自身。
bool IncludeInactive
是否包含未激活的子物体。
// ChildGameObjectsOnlyAttributeExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class ChildGameObjectsOnlyAttributeExamplesComponent : MonoBehaviour
{
[ChildGameObjectsOnly]
public Transform ChildOrSelfTransform;
[ChildGameObjectsOnly]
public GameObject ChildGameObject;
[ChildGameObjectsOnly(IncludeSelf = false)]
public Light[] Lights;
}
2.3 DisallowModificationsIn
当该对象所在的脚本挂载在何种预制体上,其修饰的对象将被禁用 / 灰色显示。
PrefabKind prefabKind
预制体的种类。
None
所有预制体,都不满足条件。
InstanceInScene
场景中的预制体实例。
InstanceInPrefab
嵌套在其他预制体中的预制件实例。
Regular
常规预制体。
Variant
预制体资产。
NonPrefabInstance
非预制体或场景中的游戏对象实例。
PrefabInstance = InstanceInPrefab | InstanceInScene
常规预制体的实例,以及场景中或嵌套在其他预制体中的预制体。
PrefabAsset = Variant | Regular
常规预制体和预制体资产。
PrefabInstanceAndNonPrefabInstance = PrefabInstance | NonPrefabInstance
预制体以及非预制实例。
All = PrefabInstanceAndNonPrefabInstance | PrefabAsset
所有预制体。
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
public class Test : MonoBehaviour
{
[DisallowModificationsIn(PrefabKind.PrefabAsset)]
public GameObject o;
}
2.4 FilePath
用于字符串,为文件路径提供接口。支持下拉选择文件路径和拖拽文件路径。
string ParentFolder
父路径。可以相对于 Unity 项目,也可以是绝对路径。
string Extensions
文件扩展名列表(以逗号分隔)。扩展名中的 “.” 可不写。
bool AbsolutePath
是否为绝对路径。
bool RequireExistingPath
true:若路径不存在,则显示警告提示。
bool UseBackslashes
是否使用反斜杠(默认使用斜杠)。
// FilePathExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class FilePathExamplesComponent : MonoBehaviour
{
// By default, FolderPath provides a path relative to the Unity project.
[FilePath]
public string UnityProjectPath;
// It is possible to provide custom parent path. Parent paths can be relative to the Unity project, or absolute.
[FilePath(ParentFolder = "Assets/Plugins/Sirenix")]
public string RelativeToParentPath;
// Using parent path, FilePath can also provide a path relative to a resources folder.
[FilePath(ParentFolder = "Assets/Resources")]
public string ResourcePath;
// Provide a comma seperated list of allowed extensions. Dots are optional.
[FilePath(Extensions = "cs")]
[BoxGroup("Conditions")]
public string ScriptFiles;
// By setting AbsolutePath to true, the FilePath will provide an absolute path instead.
[FilePath(AbsolutePath = true)]
[BoxGroup("Conditions")]
public string AbsolutePath;
// FilePath can also be configured to show an error, if the provided path is invalid.
[FilePath(RequireExistingPath = true)]
[BoxGroup("Conditions")]
public string ExistingPath;
// By default, FilePath will enforce the use of forward slashes. It can also be configured to use backslashes instead.
[FilePath(UseBackslashes = true)]
[BoxGroup("Conditions")]
public string Backslashes;
// FilePath also supports member references with the $ symbol.
[FilePath(ParentFolder = "$DynamicParent", Extensions = "$DynamicExtensions")]
[BoxGroup("Member referencing")]
public string DynamicFilePath;
[BoxGroup("Member referencing")]
public string DynamicParent = "Assets/Plugins/Sirenix";
[BoxGroup("Member referencing")]
public string DynamicExtensions = "cs, unity, jpg";
// FilePath also supports lists and arrays.
[FilePath(ParentFolder = "Assets/Plugins/Sirenix/Demos/Odin Inspector")]
[BoxGroup("Lists")]
public string[] ListOfFiles;
}
2.5 FolderPath
用于字符串,为目录路径提供接口。支持下拉选择文件夹目录和拖拽文件夹目录。
string ParentFolder
父路径。可以相对于 Unity 项目,也可以是绝对路径。
bool AbsolutePath
是否为绝对路径。
bool RequireExistingPath
true:若路径不存在,则显示警告提示。
bool UseBackslashes
是否使用反斜杠(默认使用斜杠)。
// FolderPathExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class FolderPathExamplesComponent : MonoBehaviour
{
// By default, FolderPath provides a path relative to the Unity project.
[FolderPath]
public string UnityProjectPath;
// It is possible to provide custom parent path. Parent paths can be relative to the Unity project, or absolute.
[FolderPath(ParentFolder = "Assets/Plugins/Sirenix")]
public string RelativeToParentPath;
// Using parent path, FolderPath can also provide a path relative to a resources folder.
[FolderPath(ParentFolder = "Assets/Resources")]
public string ResourcePath;
// By setting AbsolutePath to true, the FolderPath will provide an absolute path instead.
[FolderPath(AbsolutePath = true)]
[BoxGroup("Conditions")]
public string AbsolutePath;
// FolderPath can also be configured to show an error, if the provided path is invalid.
[FolderPath(RequireExistingPath = true)]
[BoxGroup("Conditions")]
public string ExistingPath;
// By default, FolderPath will enforce the use of forward slashes. It can also be configured to use backslashes instead.
[FolderPath(UseBackslashes = true)]
[BoxGroup("Conditions")]
public string Backslashes;
// FolderPath also supports member references and attribute expressions with the $ symbol.
[FolderPath(ParentFolder = "$DynamicParent")]
[BoxGroup("Member referencing")]
public string DynamicFolderPath;
[BoxGroup("Member referencing")]
public string DynamicParent = "Assets/Plugins/Sirenix";
// FolderPath also supports lists and arrays.
[FolderPath(ParentFolder = "Assets/Plugins/Sirenix")]
[BoxGroup("Lists")]
public string[] ListOfFolders;
}
2.6 MaxValue / MinValue
在 Inspector 窗口中对象能够被设置的最小 / 大值。超过该范围则会有错误提示。
double maxValue/minValue
最大 / 小值。
string Expression
用于解析最大 / 小值的字符串。可以是字段、属性、方法名或表达式。
// MinMaxValueValueExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class MinMaxValueValueExamplesComponent : MonoBehaviour
{
// Ints
[Title("Int")]
[MinValue(0)]
public int IntMinValue0;
[MaxValue(0)]
public int IntMaxValue0;
// Floats
[Title("Float")]
[MinValue(0)]
public float FloatMinValue0;
[MaxValue(0)]
public float FloatMaxValue0;
// Vectors
[Title("Vectors")]
[MinValue(0)]
public Vector3 Vector3MinValue0;
[MaxValue(0)]
public Vector3 Vector3MaxValue0;
}
2.7 MinMaxSlider
将 Vector2 向量表示为 [min, max] 区间,并在 Inspector 窗口中以滑动条方式显示。其中,x 为最小值,y 为最大值。
float minValue/maxValue
最小 / 大值。
string minValueGetter/maxValueGetter
获取最小 / 大值的方法名称。
string minMaxValueGetter
获取最小、大值对的方法名称。
bool showFields = false
是否显示对象名称。
// MinMaxSliderExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class MinMaxSliderExamplesComponent : MonoBehaviour
{
[MinMaxSlider(-10, 10)]
public Vector2 MinMaxValueSlider = new Vector2(-7, -2);
[MinMaxSlider(-10, 10, true)]
public Vector2 WithFields = new Vector2(-3, 4);
[InfoBox("You can also assign the min max values dynamically by referring to members.")]
[MinMaxSlider("DynamicRange", true)]
public Vector2 DynamicMinMax = new Vector2(25, 50);
[MinMaxSlider("Min", 10f, true)]
public Vector2 DynamicMin = new Vector2(2, 7);
[InfoBox("You can also use attribute expressions with the @ symbol.")]
[MinMaxSlider("@DynamicRange.x", "@DynamicRange.y * 10f", true)]
public Vector2 Expressive = new Vector2(0, 450);
public Vector2 DynamicRange = new Vector2(0, 50);
public float Min { get { return this.DynamicRange.x; } }
public float Max { get { return this.DynamicRange.y; } }
}
2.8 PropertyRange
创建滑块控件,将属性的值设置在指定范围之间。
double min/max
最小 / 大值。
string minGetter/maxGetter
获取最小、大值的方法名称。
// PropertyRangeExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class PropertyRangeExampleComponent : MonoBehaviour
{
[Range(0, 10)]
public int Field = 2;
[InfoBox("Odin's PropertyRange attribute is similar to Unity's Range attribute, but also works on properties.")]
[ShowInInspector, PropertyRange(0, 10)]
public int Property { get; set; }
[InfoBox("You can also reference member for either or both min and max values.")]
[PropertyRange(0, "Max"), PropertyOrder(3)]
public int Dynamic = 6;
[PropertyOrder(4)]
public int Max = 100;
}
2.9 Required
如果对象没有被关联,则显示错误信息。
string errorMessage
显示信息。
InfoMessageType messageType
信息类型。
// RequiredExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
public class RequiredExamplesComponent : MonoBehaviour
{
[Required]
public GameObject MyGameObject;
[Required("Custom error message.")]
public Rigidbody MyRigidbody;
[InfoBox("Use $ to indicate a member string as message.")]
[Required("$DynamicMessage")]
public GameObject GameObject;
public string DynamicMessage = "Dynamic error message";
}
2.10 RequiredIn
当该对象所在的脚本挂载在何种预制体上,其修饰的对象必须被关联,否则显示错误信息。
string errorMessage
显示信息。
PrefabKind prefabKind
预制体的种类。
None
所有预制体,都不满足条件。
InstanceInScene
场景中的预制体实例。
InstanceInPrefab
嵌套在其他预制体中的预制件实例。
Regular
常规预制体。
Variant
预制体资产。
NonPrefabInstance
非预制体或场景中的游戏对象实例。
PrefabInstance = InstanceInPrefab | InstanceInScene
常规预制体的实例,以及场景中或嵌套在其他预制体中的预制体。
PrefabAsset = Variant | Regular
常规预制体和预制体资产。
PrefabInstanceAndNonPrefabInstance = PrefabInstance | NonPrefabInstance
预制体以及非预制实例。
All = PrefabInstanceAndNonPrefabInstance | PrefabAsset
所有预制体。
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
public class Test : MonoBehaviour
{
[RequiredIn(PrefabKind.PrefabAsset)]
public GameObject o;
}
2.11 RequiredListLength
将 List 限制为包含指定数量的元素。
int minLength/maxLength
最小 / 大长度。
string minLengthGetter/maxLengthGetter
用于获取集合最小 / 大长度的 C# 表达式,例如“@this.otherList.Count”。
如果设置了 MinLength,则当 MinLengthGetter 返回 null 时,MinLength 将作为回退。
string fixedLengthGetter
用于获取集合长度的 C# 表达式。
PrefabKind PrefabKind
长度限制应用于哪种预制体上。
// RequiredListLengthExamplesComponent.cs
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
public class RequiredListLengthExamplesComponent : MonoBehaviour
{
[RequiredListLength(10)]
public int[] fixedLength;
[RequiredListLength(1, null)]
public int[] minLength;
[RequiredListLength(null, 10, PrefabKind = PrefabKind.InstanceInScene)]
public List<int> maxLength;
[RequiredListLength(3, 10)]
public List<int> minAndMaxLength;
public int SomeNumber;
[RequiredListLength("@this.SomeNumber")]
public List<GameObject> matchLengthOfOther;
[RequiredListLength("@this.SomeNumber", null)]
public int[] minLengthExpression;
[RequiredListLength(null, "@this.SomeNumber")]
public List<int> maxLengthExpression;
}
2.12 ValidateInput
允许检查 Inspector 窗口中拖拽关联值是否正确。
string condition
判断是否正确的方法。
string defaultMessage
显示信息。
InfoMessageType messageType
信息类型。
// ValidateInputExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;
#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endif
public class ValidateInputExamplesComponent : MonoBehaviour
{
#if UNITY_EDITOR // MyScriptyScriptableObject is an example type and only exists in the editor
[HideLabel]
[Title("Default message", "You can just provide a default message that is always used")]
[ValidateInput("MustBeNull", "This field should be null.")]
public MyScriptyScriptableObject DefaultMessage;
#endif
[Space(12), HideLabel]
[Title("Dynamic message", "Or the validation method can dynamically provide a custom message")]
[ValidateInput("HasMeshRendererDynamicMessage", "Prefab must have a MeshRenderer component")]
public GameObject DynamicMessage;
[Space(12), HideLabel]
[Title("Dynamic message type", "The validation method can also control the type of the message")]
[ValidateInput("HasMeshRendererDynamicMessageAndType", "Prefab must have a MeshRenderer component")]
public GameObject DynamicMessageAndType;
[Space(8), HideLabel]
[InfoBox("Change GameObject value to update message type", InfoMessageType.None)]
public InfoMessageType MessageType;
[Space(12), HideLabel]
[Title("Dynamic default message", "Use $ to indicate a member string as default message")]
[ValidateInput("AlwaysFalse", "$Message", InfoMessageType.Warning)]
public string Message = "Dynamic ValidateInput message";
#if UNITY_EDITOR // Editor-related code must be excluded from builds
private bool AlwaysFalse(string value) {
return false;
}
private bool MustBeNull(MyScriptyScriptableObject scripty) {
return scripty == null;
}
private bool HasMeshRendererDefaultMessage(GameObject gameObject) {
if (gameObject == null) return true;
return gameObject.GetComponentInChildren<MeshRenderer>() != null;
}
private bool HasMeshRendererDynamicMessage(GameObject gameObject, ref string errorMessage) {
if (gameObject == null) return true;
if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {
// If errorMessage is left as null, the default error message from the attribute will be used
errorMessage = "\"" + gameObject.name + "\" must have a MeshRenderer component";
return false;
}
return true;
}
private bool HasMeshRendererDynamicMessageAndType(GameObject gameObject, ref string errorMessage, ref InfoMessageType? messageType) {
if (gameObject == null) return true;
if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {
// If errorMessage is left as null, the default error message from the attribute will be used
errorMessage = "\"" + gameObject.name + "\" should have a MeshRenderer component";
// If messageType is left as null, the default message type from the attribute will be used
messageType = this.MessageType;
return false;
}
return true;
}
#endif
}