2024-07-19 Unity插件 Odin Inspector9 —— Validation Attributes

1 说明

​ 本文介绍 Odin Inspector 插件中有关验证特性的使用方法。

2 验证特性

2.1 AssetsOnly / SceneObjectsOnly

使目标对象在 Inspector 窗口中只能关联资源 / 场景对象,限制拖拽的资源类型。

image-20240715004717713
// 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

    是否包含未激活的子物体。

image-20240718021903335
// 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

    预制体的种类。

    1. None

      所有预制体,都不满足条件。

    2. InstanceInScene

      场景中的预制体实例。

    3. InstanceInPrefab

      嵌套在其他预制体中的预制件实例。

    4. Regular

      常规预制体。

    5. Variant

      预制体资产。

    6. NonPrefabInstance

      非预制体或场景中的游戏对象实例。

    7. PrefabInstance = InstanceInPrefab | InstanceInScene

      常规预制体的实例,以及场景中或嵌套在其他预制体中的预制体。

    8. PrefabAsset = Variant | Regular

      常规预制体和预制体资产。

    9. PrefabInstanceAndNonPrefabInstance = PrefabInstance | NonPrefabInstance

      预制体以及非预制实例。

    10. All = PrefabInstanceAndNonPrefabInstance | PrefabAsset

      所有预制体。

image-20240719003134858
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

    是否使用反斜杠(默认使用斜杠)。

image-20240718024034855
// 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

    是否使用反斜杠(默认使用斜杠)。

image-20240718024439650
// 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

    用于解析最大 / 小值的字符串。可以是字段、属性、方法名或表达式。

image-20240716045038267
// 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

    是否显示对象名称。

image-20240716045759075
// 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

    获取最小、大值的方法名称。

image-20240716051249151
// 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

    信息类型。

image-20240715005824011
// 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

    预制体的种类。

    1. None

      所有预制体,都不满足条件。

    2. InstanceInScene

      场景中的预制体实例。

    3. InstanceInPrefab

      嵌套在其他预制体中的预制件实例。

    4. Regular

      常规预制体。

    5. Variant

      预制体资产。

    6. NonPrefabInstance

      非预制体或场景中的游戏对象实例。

    7. PrefabInstance = InstanceInPrefab | InstanceInScene

      常规预制体的实例,以及场景中或嵌套在其他预制体中的预制体。

    8. PrefabAsset = Variant | Regular

      常规预制体和预制体资产。

    9. PrefabInstanceAndNonPrefabInstance = PrefabInstance | NonPrefabInstance

      预制体以及非预制实例。

    10. All = PrefabInstanceAndNonPrefabInstance | PrefabAsset

      所有预制体。

image-20240715232923256
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

    长度限制应用于哪种预制体上。

image-20240719004053613
// 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

    信息类型。

image-20240715011220919
// 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
}
  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔗理苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值