Unity插件——Odin使用心得(一)「建议收藏」

Unity插件——Odin使用心得(一)「建议收藏」声明:本文章为作者对Odin插件常见功能的学习笔记,仅用于学习用途.插件在活动打折时购买,本人不提供插件下载链接.系列文章目录Unity插件——Odin使用心得(一)Unity插件——Odin使用心得(一)系列文章目录一.开发环境二.使用前准备三.常用功能讲解1.命名空间2.AssetsOnly\SceneObjectsOnly:引用限制为预制体\场景物体3.Delayer:延迟赋值4.DetailedInfoBox:信息提示–标题/内容5.EnableGUI:激活GUI6.GUIColo.

大家好,又见面了,我是你们的朋友全栈君。

声明:本文为个人笔记,用于个人学习研究使用非商用,内容为个人研究及综合整理所得,若有违规,请联系,违规必改。

系列文章目录

Unity插件——Odin使用心得(一)


一.开发环境

以下为本人测试时环境:
VS版本: 2019
Odin版本:3.0.9
Unity版本:2019.3.6

二.使用前准备

1.导入插件:Unity–Asset Store–Odin–导入
2.Tools–Getting Started–Open Attributes Overview –Essentials
本文对应Essentials章节内容为基础常见功能
3.如下图所示:
在这里插入图片描述
备注:本文实例代码多来自于官方Demo示例,文末附官方手册地址.本文内容为本人总结时记录,除各特性代码实例及对应配图外多个特性名下方配有本人使用时感悟,可类比参考.本文仅对应官方手册Essentials部分,后续待更新.

三 .常用功能讲解

1.命名空间

using Sirenix.OdinInspector;

2.AssetsOnly\SceneObjectsOnly:引用限制为预制体\场景物体

限制拖拽赋值的物体来源

[Title("Assets only")]
    [AssetsOnly]
    public List<GameObject> OnlyPrefabs;

[Title("Scene Objects only")]
    [SceneObjectsOnly]
    public List<GameObject> OnlySceneObjects;

3.Delayer:延迟赋值

当脱离焦点(当前选中/选中)后赋值

  [Delayed]
    [OnValueChanged("OnValueChanged")]//当值改变时触发的事件
    public int DelayedField;
    
    // ... but the DelayedProperty can, as the name suggests, also be applied to properties.
    [ShowInInspector, DelayedProperty]
    [OnValueChanged("OnValueChanged")]
    public string DelayedProperty { 
    get; set; }
    
    private void OnValueChanged()
    { 
   
        Debug.Log("Value changed!");
    }

4.DetailedInfoBox:信息提示–标题/内容

默认显示标题文字,点击后显示内容文字

[DetailedInfoBox("Click the DetailedInfoBox...", "... to reveal more information!\n" + "This allows you to reduce unnecessary clutter in your editors, and still have all the relavant information available when required.")]
    public int Field;

   [DetailedInfoBox("标题","内容",InfoMessageType.None)]
    public int TestDetailed;

在这里插入图片描述

5.EnableGUI:激活GUI

允许复制,否则仅显示灰色不可复制

 [ShowInInspector]
    public int DisableProp1 { 
    get; }  
  
    [ShowInInspector,EnableGUI]
    public int DisableProp2 { 
    get;} 
   
    [ShowInInspector, EnableGUI]
    public int DisableProp3 { 
    get; set; }

在这里插入图片描述

此图参考:
https://zhuanlan.zhihu.com/p/408002569

6.GUIColor:改变颜色

改变字段属性颜色 方便分类或提示

[GUIColor(0.3f, 0.8f, 0.8f, 1f)]
    public int ColoredInt1;
[GUIColor("GetButtonColor")]//自动变化颜色
  private static void IAmFabulous()
    { 
   
    }
#if UNITY_EDITOR // Editor-related code must be excluded from builds
    private static Color GetButtonColor()
    { 
   
        Sirenix.Utilities.Editor.GUIHelper.RequestRepaint();
        return Color.HSVToRGB(Mathf.Cos((float)UnityEditor.EditorApplication.timeSinceStartup + 1f) * 0.225f + 0.325f, 1, 1);
    }
#endif

在这里插入图片描述

7.ButtonGroup:按钮组

将多个按钮水平放置在一组中

[ButtonGroup]
    [GUIColor(1, 0.6f, 0.4f)]
    private void Cancel()
    { 
   
    }


    [ButtonGroup]
    [GUIColor(1, 0.6f, 0.4f)]
    private void Cancel1()
    { 
   
    }


    [ButtonGroup]
    [GUIColor(1, 0.6f, 0.4f)]
    private void Cancel2()
    { 
   
    }


    [ButtonGroup]
    [GUIColor(1, 0.6f, 0.4f)]
    private void Cancel3()
    { 
   
    }

在这里插入图片描述

8.HideLabel:隐藏标签

类似隐藏变量名

[Title("Wide Colors")]
    [HideLabel]
    [ColorPalette("Fall")]
    public Color WideColor1;
    
    [HideLabel]
    [ColorPalette("Fall")]
    public Color WideColor2;
    
    [Title("Wide Vector")]
    [HideLabel]
    public Vector3 WideVector1;
    
    [HideLabel]
    public Vector4 WideVector2;

    [Title("Wide String")]
    [HideLabel]
    public string WideString;//单行 仅一行输入显示
    
    [Title("Wide Multiline Text Field")]
    [HideLabel]
    [MultiLineProperty]//字符串可多行显示
    public string WideMultilineTextField = "";

在这里插入图片描述

9.PropertyOrder:改变属性显示顺序

如下:类似定义属性时的顺序变化

 [PropertyOrder(1)]//值大最后显示
    public int Second;
    
    [InfoBox("PropertyOrder is used to change the order of properties in the inspector.")]
    [PropertyOrder(-1)]//值小优先显示
    public int First;


    public int a;//a比b先定义显示在上面
    public int b;


    public int d;//d比c先定义显示在上面
    public int c;

在这里插入图片描述

10.PropertySpace:属性空间/属性间隔

类似Unity自带的Space但可用于属性,在Inspace面板上类似行间距

 // PropertySpace and Space attributes are virtually identical...
    [Space]//仅用于字段
    public int Space;
    
    // ... but the PropertySpace can, as the name suggests, also be applied to properties.
    [ShowInInspector, PropertySpace]//可用于属性
    public string Property { 
    get; set; }
    
    // You can also control spacing both before and after the PropertySpace attribute.
    [PropertySpace(SpaceBefore = 0, SpaceAfter = 60), PropertyOrder(2)]
    public int BeforeAndAfter;

在这里插入图片描述

11.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, };

在这里插入图片描述

12.Required:必须

面板上必须赋值否则报错

[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";

在这里插入图片描述

13.Searchable:可搜索

可通过对应关键字搜索可 参考Unity Hierarchy面板上搜索

[Searchable]
public List<Perk> Perks = new List<Perk>()
{ 
   
    new Perk()
    { 
   
        Name = "Old Sage",
        Effects = new List<Effect>()
        { 
   
            new Effect() { 
    Skill = Skill.Wisdom, Value = 2, },
            new Effect() { 
    Skill = Skill.Intelligence, Value = 1, },
            new Effect() { 
    Skill = Skill.Strength, Value = -2 },
        },
    },
    new Perk()
    { 
   
        Name = "Hardened Criminal",
        Effects = new List<Effect>()
        { 
   
            new Effect() { 
    Skill = Skill.Dexterity, Value = 2, },
            new Effect() { 
    Skill = Skill.Strength, Value = 1, },
            new Effect() { 
    Skill = Skill.Charisma, Value = -2 },
        },
    },
    new Perk()
    { 
   
        Name = "Born Leader",
        Effects = new List<Effect>()
        { 
   
            new Effect() { 
    Skill = Skill.Charisma, Value = 2, },
            new Effect() { 
    Skill = Skill.Intelligence, Value = -3 },
        },
    },
    new Perk()
    { 
   
        Name = "Village Idiot",
        Effects = new List<Effect>()
        { 
   
            new Effect() { 
    Skill = Skill.Charisma, Value = 4, },
            new Effect() { 
    Skill = Skill.Constitution, Value = 2, },
            new Effect() { 
    Skill = Skill.Intelligence, Value = -3 },
            new Effect() { 
    Skill = Skill.Wisdom, Value = -3 },
        },
    },
};
[Serializable]
public class Perk
{ 
   
    public string Name;
    [TableList]
    public List<Effect> Effects;
}
[Serializable]
public class Effect
{ 
   
    public Skill Skill;
    public float Value;
}
public enum Skill
{ 
   
    Strength,
    Dexterity,
    Constitution,
    Intelligence,
    Wisdom,
    Charisma,
}

搜索前:
在这里插入图片描述
搜索后
在这里插入图片描述

14.ShowInInspector:属性显示在Inspector面板

可将(包括静态的)属性显示在Inspector面板上

 [ShowInInspector]
    private int myPrivateInt;
    
    [ShowInInspector]
    public int MyPropertyInt { 
    get; set; }
    
    [ShowInInspector]
    public int ReadOnlyProperty
    { 
   
        get { 
    return this.myPrivateInt; }
    }
    
    [ShowInInspector]
    public static bool StaticProperty { 
    get; set; }
    [ShowInInspector]
    public static string StaticStringProperty { 
    get; set; }

在这里插入图片描述

15.Title:标题用于在属性上方制作粗体标题

可用于方法属性字段

 [Title("Titles and Headers")]
    public string MyTitle = "My Dynamic Title";
    public string MySubtitle = "My Dynamic Subtitle";
    
    [Title("Static title")]
    public int C;
    public int D;
    
    [Title("Static title", "Static subtitle")]
    public int E;
    public int F;

在这里插入图片描述

16.TypeFilter: 对基础过滤,显示需要(子类)的属性

例如:基类为BaseClass 可以在Inspace面板设置显示对应的子类属性

// TypeFilterExamplesComponent.cs
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;


public class TypeFilterExamplesComponent : SerializedMonoBehaviour
{ 
   
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass A, B;
    
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass[] Array = new BaseClass[3];
    
    public IEnumerable<Type> GetFilteredTypeList()
    { 
   
        var q = typeof(BaseClass).Assembly.GetTypes()
            .Where(x => !x.IsAbstract)                                          // Excludes BaseClass
            .Where(x => !x.IsGenericTypeDefinition)                             // Excludes C1<>
            .Where(x => typeof(BaseClass).IsAssignableFrom(x));                 // Excludes classes not inheriting from BaseClass
    
        // Adds various C1<T> type variants.
        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; }
}

在这里插入图片描述

17.TypeInfoBox:类型信息框属性

属性将一个信息框添加到检查器中类型的最顶部。使用它可以将信息框添加到检查器中类的顶部,而不必使用 PropertyOrder 和 OnInspectorGUI 属性。

public MyType MyObject = new MyType();
[InfoBox("Click the pen icon to open a new inspector for the Scripty object.")]
[InlineEditor]
public MyScriptyScriptableObject Scripty;
[Serializable]
[TypeInfoBox("The TypeInfoBox attribute can be put on type definitions and will result in an InfoBox being drawn at the top of a property.")]
public class MyType
{ 
   
    public int Value;
}
//[TypeInfoBox("The TypeInfoBox attribute can also be used to display a text at the top of, for example, MonoBehaviours or ScriptableObjects.")]
//public class MyScriptyScriptableObject : ScriptableObject
//{ 
   
// public string MyText = ExampleHelper.GetString();
// [TextArea(10, 15)]
// public string Box;
//}
[OnInspectorInit]
private void CreateData()
{ 
   
    Scripty = ExampleHelper.GetScriptableObject<MyScriptyScriptableObject>("Scripty");
}
[OnInspectorDispose]
private void CleanupData()
{ 
   
    if (Scripty != null) UnityEngine.Object.DestroyImmediate(Scripty);
}

在这里插入图片描述在这里插入图片描述

18.AssetsOnly\SceneObjectsOnly:引用限制为预制体\场景物体

限制拖拽赋值的物体来源

[Title("Assets only")]
    [AssetsOnly]
    public List<GameObject> OnlyPrefabs;

[Title("Scene Objects only")]
    [SceneObjectsOnly]
    public List<GameObject> OnlySceneObjects;

19.ValidateInput:输入验证

用于任何属性,并允许验证来自 inspector面板的输入。使用它来强制执行正确的值。

[ValidateInput("CheckSex", "", InfoMessageType.Error)]
    public string sex;
    public bool CheckSex(string sex, ref string errorMessage, ref InfoMessageType? messageType)
    { 
   
        errorMessage = "性别输入错误";
        return sex == "男";
    }  

输入错误值:
在这里插入图片描述

输入正确值:

在这里插入图片描述

20.ValueDropdown 用于任何属性,并创建一个带有可配置选项的下拉列表。

使用它为用户提供一组特定的选项以供选择。(带枚举器类型产生类似枚举的下拉框)

 [ValueDropdown("TextureSizes")]
    public int SomeSize1;
    
    [ValueDropdown("FriendlyTextureSizes")]
    public int SomeSize2;
    
    [ValueDropdown("FriendlyTextureSizes", AppendNextDrawer = true, DisableGUIInAppendedDrawer = true)]
    public int SomeSize3;
    
    [ValueDropdown("GetListOfMonoBehaviours", AppendNextDrawer = true)]
    public MonoBehaviour SomeMonoBehaviour;
    
    [ValueDropdown("KeyCodes")]
    public KeyCode FilteredEnum;
    
    [ValueDropdown("TreeViewOfInts", ExpandAllMenuItems = true)]
    public List<int> IntTreview = new List<int>() { 
    1, 2, 7 };
    
    [ValueDropdown("GetAllSceneObjects", IsUniqueList = true)]
    public List<GameObject> UniqueGameobjectList;
    
    [ValueDropdown("GetAllSceneObjects", IsUniqueList = true, DropdownTitle = "Select Scene Object", DrawDropdownForListElements = false, ExcludeExistingValuesInList = true)]
    public List<GameObject> UniqueGameobjectListMode2;
    
#if UNITY_EDITOR // Editor-related code must be excluded from builds
#pragma warning disable // And these members are in fact being used, though the compiler cannot tell. Let's not have bothersome warnings.
    private IEnumerable TreeViewOfInts = new ValueDropdownList<int>()
    { 
   
        { 
    "Node 1/Node 1.1", 1 },
        { 
    "Node 1/Node 1.2", 2 },
        { 
    "Node 2/Node 2.1", 3 },
        { 
    "Node 3/Node 3.1", 4 },
        { 
    "Node 3/Node 3.2", 5 },
        { 
    "Node 1/Node 3.1/Node 3.1.1", 6 },
        { 
    "Node 1/Node 3.1/Node 3.1.2", 7 },
    };
    
    private IEnumerable<MonoBehaviour> GetListOfMonoBehaviours()
    { 
   
        return GameObject.FindObjectsOfType<MonoBehaviour>();
    }
    
    private static IEnumerable<KeyCode> KeyCodes = Enumerable.Range((int)KeyCode.Alpha0, 10).Cast<KeyCode>();
    
    private static IEnumerable GetAllSceneObjects()
    { 
   
        Func<Transform, string> getPath = null;
        getPath = x => (x ? getPath(x.parent) + "/" + x.gameObject.name : "");
        return GameObject.FindObjectsOfType<GameObject>().Select(x => new ValueDropdownItem(getPath(x.transform), x));
    }
    
    private static IEnumerable GetAllScriptableObjects()
    { 
   
        return UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject")
            .Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x))
            .Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<ScriptableObject>(x)));
    }
    
    private static IEnumerable GetAllSirenixAssets()
    { 
   
        var root = "Assets/Plugins/Sirenix/";
    
        return UnityEditor.AssetDatabase.GetAllAssetPaths()
            .Where(x => x.StartsWith(root))
            .Select(x => x.Substring(root.Length))
            .Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(root + x)));
    }
    
    private static IEnumerable FriendlyTextureSizes = new ValueDropdownList<int>()
    { 
   
        { 
    "Small", 256 },
        { 
    "Medium", 512 },
        { 
    "Large", 1024 },
    };
    
    private static int[] TextureSizes = new int[] { 
    256, 512, 1024 };
#endif

在这里插入图片描述

四.总结

本文为作者对Odin插件的使用总结,因整个插件内容较多,篇幅过长,参考官方实例结构,该章节仅描述了Essentials部分,后续更新后会在本文开头及文章末尾附上链接.,学习建议以官方文档为主.

五:相关链接

Odin官方手册地址:
https://odininspector.com/attributes/value-dropdown-attribute

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/162839.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QuoteName\生成Sql语句

    QuoteName\生成Sql语句ifexists(selectnamefromtempdb.dbo.sysobjectswhereid=object_id(N’tempdb.dbo.#tempWorkDate’)andtype=’u’)droptable#tempWorkDateCREATETABLE[#tempWorkDate]([WorkDate][varc…

    2022年7月25日
    5
  • C语言实现电脑关机程序

    C语言实现电脑关机程序这个是我在网上搜索到的资料,其实也是很简单的。想使用ESP8266完成这样一个操作——远程关闭电脑,达到人在别的任何地方都可以操作我们的电脑。这个虽然已经不是羡慕新奇的事,实现的方法也撑出不穷,但我们学习ESP8266,也不失是一种体验的过程。对于初学者来说也是一种很有成就感的体验。因此,想完成远程关机,就需要理解怎么实现关机的命令及程序,我们使用C语言来完成。串口助手也可以实…

    2022年7月22日
    11
  • mac 电脑android环境变量设置,mac上Android环境变量配置[通俗易懂]

    mac 电脑android环境变量设置,mac上Android环境变量配置[通俗易懂]1.AndroidSDK路径查看(1)AndroidStudio:菜单栏AndroidStudio>Preferences>Appearences&Behavior>SystemSettins>AndroidSDKtab中的SDKLocation。(2)Eclipse:菜单栏Eclipse>Preferences>Andr…

    2022年6月25日
    20
  • Mac Quicktime 录屏带声音[通俗易懂]

    Mac Quicktime 录屏带声音[通俗易懂]最近有录屏的需求,但是Mac大多数录屏软件都收费,之前用Windows时用EV录屏,免费好用,可惜没有Mac版。Mac自带的QuickTime软件虽然能录屏,但是不能录制声音,很苦恼。直到我发现了SoundFlower软件。1、下载安装soundflower给个链接:http://mysoft.6h5.cn/Soundflower-2.0b2.dmg安…

    2022年5月3日
    88
  • wangEditor的使用

    wangEditor的使用wangEditor的使用第一步,将其下载,并引入项目中。第二步,引入js第三步,初始化对象第四步,添加一些配置配置菜单配置图片上传第五步,设置内容第六步,获取内容很好,很方便!

    2022年8月2日
    3
  • VS2008安装失败原因!「建议收藏」

    VS2008安装失败原因!「建议收藏」从RTM到现在,我已安装十多回VS2008,发现总会安装OfficeTools的时候,会失败。百思不知其解。后在网上看到,是因为我们使用UltraISO制作激活成功教程的VS2008的时候带出来的问题,主要是Unicode的问题。于是我这个怎么解决呢?我尝试先用deamon打开原版的vs2008,再用untraISO将虚拟盘的所以文件加入新的ISO中,再将激活成功教程的setup.那个文件,加入。重新生成iso

    2022年9月6日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号