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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • js面试笔试–prototype详解

    js面试笔试–prototype详解对JavaScript中原型模式的理解一:什么是原型对象?有什么优点?   简单的来说,无论何时,我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。其实我们平常的叫法就是指:prototype就是通过该构造函数创建的某个实例的原型对象,但是其实prototype是每个构造函数的属性而已,只能说…

  • 手机号码归属地查询数据库下载「建议收藏」

    手机号码归属地查询数据库下载「建议收藏」只需要输入前7位即可查询所在地access数据库,excel的可以直接查询哦,还有htm格式下载。有15万5千多条记录电话区号code字段2009年01月02日整理完成支持移动159号段和联通153号段包含最新的151、155、157号码段的归属地数据手机号码归属地信息,可以详细查询到手机号码的开户地信息,包括该号码所属省份、城市、长途区号以及该号…

  • pytest parametrize fixture_参数化数据

    pytest parametrize fixture_参数化数据前言当某个接口中的一个字段,里面规定的范围为1-5,你5个数字都要单独写一条测试用例,就太麻烦了,这个时候可以使用pytest.mark.parametrize装饰器可以实现测试用例参数化。官方示

  • 如何利用Javascript发送GET/POST请求「建议收藏」

    如何利用Javascript发送GET/POST请求「建议收藏」如何利用Javascript发送GET/POST请求最近在做基于TWS的分析系统,因为采用Flask+Java的技术架构方案,所以需要开发Web,然而我自己没有做过类似的开发,所以很多工作是从头开始学着做的。因此,在实现表单数据提交的时候,当时就想到个问题,如果一个页面里内容足够多的话,仅用form提交的话,后台就需要做非常复杂的判断,以此确认用户提交的是哪类数据,这样工程不仅难看,而且低效。于是咨

  • python求组合数cnm公式_组合数公式推导Cnm = n! / [(n-m)! * m!]「建议收藏」

    python求组合数cnm公式_组合数公式推导Cnm = n! / [(n-m)! * m!]「建议收藏」展开全部cnm的意思是从n个中取m个无排列的个数,可如此思考,先取e5a48de588b63231313335323631343130323136353331333431336230第一个,有n种取法,第二个有n-1种取法……第m个有n+1-m种取法,这些取法相乘即为n!/(n-m)!但这种取法实际上为这取的m个排序了,换句话说这是排序了以后的个数,而我们所要的是不排序的个数,那么m个排序…

  • sensor DVP接口介绍

    sensor DVP接口介绍转载:https://blog.csdn.net/hua371242480/article/details/88629023原创sensor接口之DVP…

发表回复

您的电子邮箱地址不会被公开。

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