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

系列文章目录

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


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

  • 系列文章目录
  • 一.开发环境
  • 二.使用前准备
  • 三 .常用功能讲解
    • 1.命名空间
    • 2.AssetsOnly\SceneObjectsOnly:引用限制为预制体\场景物体
    • 3.Delayer:延迟赋值
    • 4.DetailedInfoBox:信息提示--标题/内容
    • 5.EnableGUI:激活GUI
    • 6.GUIColor:改变颜色
    • 7.ButtonGroup:按钮组
    • 8.HideLabel:隐藏标签
    • 9.PropertyOrder:改变属性显示顺序
    • 10.PropertySpace:属性空间/属性间隔
    • 11.ReadOnly:只读
    • 12.Required:必须
    • 13.Searchable:可搜索
    • 14.ShowInInspector:属性显示在Inspector面板
    • 15.Title:标题用于在属性上方制作粗体标题
    • 16.TypeFilter: 对基础过滤,显示需要(子类)的属性
    • 17.TypeInfoBox:类型信息框属性
    • 18.AssetsOnly\SceneObjectsOnly:引用限制为预制体\场景物体
    • 19.ValidateInput:输入验证
    • 20.ValueDropdown 用于任何属性,并创建一个带有可配置选项的下拉列表。
  • 四.总结
  • 五:相关链接

一.开发环境

以下为本人测试时环境:
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 buildsprivate 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

Unity插件——Odin使用心得(一)相关推荐

  1. 神器-unity插件-Odin

    https://blog.csdn.net/weixin_34221073/article/details/93707400

  2. Asset Store上常用的40个Unity插件汇总——进阶开发者必备Unity插件

    上篇文章着重介绍了Unity Asset Store(Unity资源商店)上一些超棒的资源与素材. unity老司机的资源推荐与常用插件汇总合集 - 简书 Unity插件资源购买小技巧 - 简书 本篇 ...

  3. 【Unity插件】最多的插件合集

    一.前言 ? 最近整理了一下文章,发现我分享了很多的插件,但是如果要查找某一款插件,还需要去搜索才能找到,很不方面,就想要将写过的所有的插件分享也好,教程也好,做一个汇总,然后这篇文章还会不断的更新, ...

  4. Unity插件之NGUI学习(4)—— 创建UI2DSprite动画

    创建一个新的Scene.并按 Unity插件之NGUI学习(2)创建UI Root,并在UI Root的Camera下创建一个Panel. 然后在选中Panel,在菜单中选择NGUI->Crea ...

  5. Unity GUI(uGUI)使用心得与性能总结

    Unity GUI(uGUI)使用心得与性能总结 作者 kingshijie 关注 2015.09.26 15:35 字数 3686 阅读 28031评论 10喜欢 49 背景和目的 小哈接触Unit ...

  6. Unity插件-NGUI使用教程

    Unity插件-NGUI使用教程 本文提供全流程,中文翻译. Chinar坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 NGUI 一款强大 ...

  7. Unity插件之NGUI学习(8)—— Table和NGUI尺寸转换为世界坐标系尺寸

    依据 Unity插件之NGUI学习(2),创建一个UI Root,在UI Root下创建一个Texture作为背景图,并设置图片,在Wiget下调整大小:然后在UI Root下再创建一个Panel. ...

  8. UNITY插件信息收集

    UNITY插件信息收集 2018.8.7 UNITY超级优化神器 : Amplify Impostors posted on 2018-08-07 20:53 时空观察者9号 阅读(...) 评论(. ...

  9. AR+LBS街景实景红包PokemonGo游戏捉妖夺宝营销解决方案定制开发暨百度高德地图Unity插件SDK

    AR+LBS街景实景红包PokemonGo游戏捉妖夺宝营销解决方案定制开发暨百度高德地图Unity插件SDK 作者 komstone https://blog.csdn.net/komstone/ar ...

  10. 3ds max sdk导出插件编写的心得

    3ds max sdk导出插件编写的心得 作者:yhchinabest 来自:CG先生-3D图形插件开发网http://www.cgsir.com 写在前面 为什么要写这个心得?去年11月份的时候我写 ...

最新文章

  1. 在ubuntu系统荣品开发配套JDK安装
  2. Windows环境下QWT安装及配置
  3. scara机器人dh参数表_两分钟带你了解机器人标定的因素
  4. C++0x,崭新的C++,还是另一个JAVA?
  5. Mr.J-- jQuery学习笔记(十一)--事件委托
  6. Kubernetes-保障集群内节点和网络安全
  7. Web测试中新增修改功能测试
  8. python解压.tar.gz
  9. mktime()的格式
  10. 2018毕业设计需求分析
  11. 家庭局域网_分析 | 如何查询局域网内在用的IP地址?
  12. 带软开启功能的MOS管电源开关电路!
  13. ekl中logstash的导入配置
  14. 分享免费的主流电商平台商品图片批量下载方法
  15. NLPCC2021.10.14
  16. 解决虚拟机-虚拟网络配置没有桥接模式,本地没有虚拟网卡
  17. prometheus 监控交换机流量
  18. 笔记:戴蒙德模型——参数变化的影响
  19. 云计算 - 虚拟化技术Overview
  20. 面试了10几家软件公司测试岗位,做的面试题大盘点,重点大合集

热门文章

  1. 互补滤波 二阶低通滤波理解
  2. 惊呼!633个中国城市数据调查:五分之二的城市在流失人口
  3. GitHub Top 100的Android开源库
  4. wo-mic ,audioRelay设置
  5. 自定义C语言头文件书写格式
  6. W3school离线手册最新版下载
  7. web前端学习资源分享
  8. 关于UML 画图工具EA 在linux下的安装和界面配置
  9. 关于switch软破“由于发生错误,软件已关闭”无法升级主机系统等问题
  10. matlab covar,delta CoVaR 系统性风险指标计算