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)
blank

相关推荐

  • javaweb-springboot-2-73

    javaweb-springboot-2-73

  • JAVA生成uuid_uuidJDK生成代码

    JAVA生成uuid_uuidJDK生成代码uuid作为通用识别码,其java的实现版本如下,本文以将url(https://blog.csdn.net/renyuanfang/article/details/86701148)转换成uuid为例,实现具体的代码实现importjava.util.UUID;importjava.nio.ByteBuffer;importjava.nio.ByteOrder;impor…

  • Cloudsim学习笔记——基本知识

    Cloudsim学习笔记——基本知识Cloudsim澳大利亚墨尔本学校的网格实验室和Gridbus项目推出,是在离散事件模拟包SimJava上开发的函数库,继承了GridSim的编程模型,特点:支持大型云计算的基础设施的建模和仿真; 一个自足的支持数据中心、服务代理人、调度和分配策略的平台独特功能:提供虚拟化引擎,旨在数据中心节点上帮助建立和管理多重的、独立的、协调的虚拟化服务; 在对虚拟化服务分配处理核心时能够在时…

    2022年10月13日
  • Latex如何插入图片[通俗易懂]

    Latex如何插入图片[通俗易懂]在写报告或论文的过程中,几乎不可避免的要插入一些图片,并且根据不同情况及要求进行排版,例如如何插入单个图片、一行插入两张图片、插入两行两列图片等等。在此,汇总一下各种插入图片的方法。插入单个图片这种情况是最简单的了,当然使用latex排版时也要注意一些问题,比如相关宏包的引用、图片存放路径、图片尺寸及位置调整等,下面给出一例子。代码:\documentclass{article}\use…

  • Android 打包出现jdk版本错误的问题

    Android 打包出现jdk版本错误的问题

  • 常用端口列表[通俗易懂]

    常用端口列表[通俗易懂]常见端口0|无效端口,通常用于分析操作系统1|传输控制协议端口服务多路开关选择器2|管理实用程序3|压缩进程5|远程作业登录7|回显9|丢弃11|在线用户13|时间17|每日引用18|消息发送协议19|字符发生器20|FTP文件传输协议(默认数据口)21|FTP文件传输协议(控制)22|SSH远程登录协议23|telnet(终端仿真协议),木马TinyTelnetServer开放此端口24|预留给个人用邮件系统25|SMTP服务器所…

发表回复

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

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