SaintsField Documentation

repository·master·Indexed 20 days ago

https://github.com/tylertemp/saintsfield

A Unity plugin (version 5.25.5) for enhancing the Inspector and data serialization. It provides advanced attributes for grouping fields, serializing complex types like dictionaries and interfaces, and customizing the developer experience with tools such as LabelText, InfoBoxes, and separators.

Tokens
57.7K
Snippets
166
Records
194
Agent score
71%

What's inside SaintsField

  1. Explore SaintsField General Attributes

    master

    SaintsField provides a wide range of attributes to customize the Unity Inspector. These attributes are categorized by their functional purpose:

    • Label & Text: Control how labels and text are displayed (e.g., LabelText, AboveText, OverlayText, Separator).
    • Button: Add interactive buttons to the inspector (e.g., Button, PostFieldButton).
    • Game Related: Link inspector fields to Unity engine concepts (e.g., Layer, Scene, Tag, InputAxis, ShaderParam).
    • Toggle & Switch: Create visual toggles for various types (e.g., GameObjectActive, SpriteToggle, MaterialToggle).
    • Data Editor: Enhance data visualization and selection (e.g., Expandable, ReferencePicker, Table, ShowInInspector).
    • Numerical: Specialized controls for numbers (e.g., Rate, PropRange, MinMaxSlider, ProgressBar).
    • Animation: Control animation parameters (e.g., AnimatorParam, AnimatorState, CurveRange).
    • Auto Getter: Automatically fetch components or objects (e.g., GetComponent, GetInScene, GetMainCamera, AddComponent).
    • Validate & Restrict: Enforce rules on field values (e.g., ReadOnly, ShowIf, RequiredIf, MinValue, ArraySize).
    • Miscellaneous: Various UI enhancements (e.g., Dropdown, ValueButtons, ColorPalette, Searchable, DateTime).
  2. Serialize long/ulong based Enums

    master

    Unity does not support enums with a long or ulong base type. You can bypass this limitation by applying [SaintsSerialized] to the enum field.

    Requirements:

    1. The containing MonoBehaviour/ScriptableObject must be partial.
    2. The enum field must have the [SaintsSerialized] attribute.
    3. If the enum is used inside a normal class/struct, that class/struct must also be partial.

    EnumToggleButtons is fully supported with these enums.

    public partial class MyBehavior: MonoBehaviour
    {
        [Flags]
        public enum TestULongEnum: ulong
        {
            None = 0,
            First = 1,
            Second = 1 << 1,
        }
    
        [SaintsSerialized] public TestULongEnum ULongEnumPub;
        [SaintsSerialized, EnumToggleButtons] public TestULongEnum ULongEnumPubBtns;
    }
  3. Use AI Navigation attributes for Unity NavMesh

    master

    SaintsField provides tools for Unity AI Navigation (NavMesh) in the SaintsField.AiNavigation namespace. These are only active if the AI Navigation package is installed.

    To disable these components, add the macro SAINTSFIELD_AI_NAVIGATION_DISABLED to your project.

    Available Attributes:

    • [NavMeshAreaMask]: A picker to select a NavMesh area bit mask for an integer field.
    • [NavMeshArea]: A picker to select a NavMesh area for string or integer fields, with support for bit masks or single area values.
    using SaintsField.AiNavigation;
    
    [NavMeshAreaMask]
    public int areaMask;
    
    [NavMeshArea]
    public int areaSingleMask;
  4. Understand EMode values

    master

    The EMode enum is used to determine the current context of the Unity Editor or the target object:

    • EMode.Edit: Editor is not playing.
    • EMode.Play: Editor is playing.
    • EMode.InstanceInScene: Target is a prefab placed in a scene.
    • EMode.InstanceInPrefab: Target is inside a prefab (but not the root).
    • EMode.Regular: Target is at the top root of a prefab.
    • EMode.Variant: Target is a variant prefab root.
    • EMode.NonPrefabInstance: Target is not a prefab.
    • EMode.PrefabInstance: Alias for InstanceInPrefab | InstanceInScene.
    • EMode.PrefabAsset: Alias for Variant | Regular.
  5. Use Unity-specific axes for resource traversal

    master

    In addition to standard axes like ancestor::, ancestor-or-self::, parent::, and parent-or-self::, Saints XPath provides specialized axes to target Unity-specific resources:

    • ancestor-inside-prefab::: Traverses ancestors within a prefab boundary.
    • ancestor-or-self-inside-prefab::: Traverses ancestors or self within a prefab boundary.
    • parent-inside-prefab::: Traverses the parent within a prefab boundary.
    • parent-or-self-inside-prefab::: Traverses the parent or self within a prefab boundary.
    • scene::: Targets the scene root node.
    • prefab::: Targets the prefab root node.
    • resources::: Targets resources.
    • asset::: Targets AssetDatabase resources.
  6. Use Spine attributes for robust references

    master

    SaintsField provides a suite of attributes in the SaintsField.Spine namespace that improve upon standard Unity Spine attributes. These attributes support searching, are compatible with the Auto Validator tool, and work with Unity's default right-click context menu.

    Most attributes allow you to specify a skeletonTarget (a SkeletonData, SkeletonRenderer, component, or GameObject with a SkeletonRenderer) to define the source of the data. If null, it defaults to GetComponent<SkeletonRenderer>() on the current object.

    using SaintsField.Spine;
    
    // Example of targeting a specific field as the source
    public SkeletonAnimation _spine;
    [SpineAnimationPicker(nameof(_spine))] private AnimationReferenceAsset animationRef;
  7. Inspect Interfaces and Dictionaries in the Inspector

    master

    SaintsField allows you to inspect interfaces and collections like Dictionary<TKey, TValue> or IReadOnlyDictionary<TKey, TValue> directly in the Unity Inspector using the [ShowInInspector] attribute. For interfaces, the inspector will automatically show an object picker or a field editor depending on whether the underlying type is a UnityObject or a general class/struct.

    public class GeneralDummyClass: IDummy
    {
        public string GetComment() => "DummyClass";
        public int MyInt { get; set; }
        public int GenDumInt;
        public string GenDumString;
    }
    
    [ShowInInspector] private static IDummy _dummy;
    
    [Button]
    private void DebugDummy() => Debug.Log(_dummy);
  8. Serialize Dictionary<,> and HashSet<>

    master

    You can serialize Dictionary<,> and HashSet<> directly by applying [SaintsSerialized].

    • Dictionaries: Internally uses SaintsDictionary for serialization. This supports interfaces as keys or values and can be nested inside arrays or lists.
      • Note for Callbacks: If using [OnValueChanged], the callback parameter must be typed as IDictionary<,> or SaintsDictionary<,>.
    • HashSets: Supports serializable types, abstract classes/structs, and interface types as element types.

    Requirement: The containing class/struct must be partial.

    public partial class SerDictionaryExample : MonoBehaviour
    {
        // Dictionary support
        [SaintsSerialized] public Dictionary<int, IInterface1> _dictInterface;
        [SaintsSerialized] private List<Dictionary<IInterface1, IInterface1>> _dictInterfaceLis;
    
        // Dictionary OnValueChanged callback requirement
        [SaintsSerialized, OnValueChanged(nameof(ChangedWatcher))] 
        private Dictionary<string, int> _myDictionary;
        private void ChangedWatcher(IDictionary<string, int> dic) => Debug.Log(dic);
    
        // HashSet support
        [SaintsSerialized] public HashSet<string> stringHashSet;
        [SaintsSerialized] public HashSet<IInterface1> refHashSet;
    }
  9. Implement custom search logic for lists

    master

    To implement custom search logic, provide a method name to the extraSearch or overrideSearch parameters of [ListDrawerSettings].

    Supported Method Signatures:

    • bool CustomSearch(T item, int index, IReadOnlyList<ListSearchToken> searchToken)
    • bool CustomSearch(T item, IReadOnlyList<ListSearchToken> searchToken)
    • bool CustomSearch(int index, IReadOnlyList<ListSearchToken> searchToken)

    ListSearchToken Structure:

    • ListSearchType Type: The filter type (Include or Exclude).
    • string Token: The search string used for filtering.
    [Serializable]
    public struct Weapon
    {
        public WeaponType weaponType;
        public string description;
    }
    
    private bool ExtraSearch(Weapon weapon, int _, IReadOnlyList<ListSearchToken> tokens)
    {
        string searchName = new Dictionary<WeaponType, string>
        {
            { WeaponType.Arch , "弓箭 双手" },
            { WeaponType.Sword , "刀剑 单手" },
            { WeaponType.Hammer, "大锤 双手" },
        }[weapon.weaponType];
        return RuntimeUtil.SimpleSearch(searchName, tokens);
    }
    
    [ListDrawerSettings(extraSearch: nameof(ExtraSearch))]
    public Weapon[] weapons;
  10. Create nested and grouped items in Dropdowns

    master

    You can create hierarchical dropdown menus by nesting Dropdown<T> objects within each other. A Dropdown<T> item can either be a direct value or a group containing IEnumerable<Dropdown<T>> children. You can also insert separators using Dropdown<T>.Separator().

    [Dropdown(nameof(AdvDropdown))] public int drops;
    
    public Dropdown<int> AdvDropdown()
    {
        return new Dropdown<int>("First Half")
        {
            new Dropdown<int>("Monday", 1, icon: "eye.png"),
            new Dropdown<int>("Tuesday", 2),
        };
    }
  11. Understand the Saints XPath syntax and structure

    master

    Saints XPath is a subset of the standard XPath language designed for Unity. It uses a step-based structure to traverse nodes.

    Basic Structure: step/step/step/...

    A step follows the pattern: axisname::nodetest[predicate]

    Key Syntax Rules:

    • Axes and Attributes: You can select attributes using @. For example, name@attribute is valid, but you cannot mix :: and @ in the same segment (e.g., ancestor::name@attr is invalid; use ancestor::name/@attr instead).
    • Predicates: Predicates are enclosed in square brackets []. They can filter by attributes using @, but they do not select the attribute itself.
    • Predicates Requirement: There must be a space before the predicate (e.g., node [@attr=val]).
    • Limitations: Complex XPath features like forward/backward assertions (e.g., name[ancestor::note()[@attr=1]]) are not supported.