Odin扩展Inspector窗口
最大的应用是和扩展 EditorWindow 结合,做一些编辑器工具
参考 https://odininspector.com/tutorials/using-attributes/simple-attribute-examples
扩展属性的选择和验证
-
public class OdinChecker : MonoBehaviour { [Range(0, 10)] public int Field = 2; [MinValue(0), MaxValue(100)] public int Health; [ChildGameObjectsOnly] public GameObject Child; // 验证字符串指向的是否是某类型对象 [RequiredIn(PrefabKind.InstanceInPrefab)] public string InstanceInPrefab = "Instances of prefabs nested inside other prefabs"; // 验证值是否存在,如果是 GameObject 也会验证对象是否存在,参数是不存在时的提示 [Required("Missing DynamicExtensions")] public string DynamicExtensions = "cs, unity, jpg"; // 可以把资源拖进来获取路径,或打开打开文件窗口定位文件路径 // 默认转成相对Unity工程根路径(Assets/../)的路径,可以用 ParentFolder 指定相对哪个目录 // Extensions 指定扩展名,RequireExistingPath 验证文件是否存在,AbsolutePath 取绝对路径 // ParentFolder 和 Extensions 还可以使用变量名,比如 Extensions="$DynamicExtensions" [FilePath(ParentFolder = "Assets/Resources", Extensions = "cs,js", RequireExistingPath = true, AbsolutePath = true)] public string UnityProjectPath; // 同 FilePath [FolderPath(ParentFolder = "Assets/Resources", RequireExistingPath = true, AbsolutePath = true)] public string UnityProjectFolder; // 只能关联 Project 中的对象 [AssetsOnly] public GameObject SomePrefab; // 只能关联 Hierarchy 中的对象 [SceneObjectsOnly] public GameObject SomeSceneObject; // 验证值,指定一个验证函数,后面是验证不通过时的提示 [ValidateInput("HasMeshRendererDefaultMessage", "Prefab must have a MeshRenderer component")] public GameObject DynamicMessage; private bool HasMeshRendererDefaultMessage(GameObject gameObject) { if (gameObject == null) return true; return gameObject.GetComponentInChildren<MeshRenderer>() != null; } }
扩展属性显示
-
public class OdinSimple : MonoBehaviour { // HideLabel 不显示标题 // PropertyOrder 可调整属性显示顺序,越小越优先 // 注意不只会提升该属性优先级,还会提升分组,父分组的优先级 [HideLabel, PropertyOrder(-3)] public int Age; // 定义标题宽度 [TableColumnWidth(50)] public string Name; // 定义按钮,显示标题为 RandomName,点击调用 RandomName [Button(ButtonSizes.Medium), GUIColor(0, 1, 0)] public void RandomName() { } // Icon 在左边, Properties 分组在右边 // HideLabel 不显示标题, PreviewField 用矩形窗口替代对象框,可用来预览 [HorizontalGroup("Split", Width = 50), HideLabel, PreviewField(50)] public Texture2D Icon; [VerticalGroup("Split/Properties")] public string MinionName; // LabelText 定制标题,可以使用其它变量 [VerticalGroup("Split/Properties"),LabelText("$MinionName")] public float Health; // ListDrawerSettings 可以定制列表项的创建和删除 [ListDrawerSettings( CustomAddFunction = "CreateNewGUID", CustomRemoveIndexFunction = "RemoveGUID")] public List<string> GuidList; private string CreateNewGUID() { return Guid.NewGuid().ToString(); } private void RemoveGUID(int index) { this.GuidList.RemoveAt(index); } // 必须添加 Serializable 特性 [Serializable] public struct Item { public string name; public int num; } // 添加 TableList 可以像 excel 表格一样进行配置 [TableList] public List<Item> ItemList; }
扩展属性布局
-
public class OdinGroup : MonoBehaviour { // 创建Tab页,Group名称省略的话默认为 _DefaultTabGroup [TabGroup("Tab1")] public int dataInTab1; [TabGroup("Tab1")] public int data2InTab1; [TabGroup("Tab2")] public int dataInTab2; // 有多个 Group 的时候,Group 名称就不能省略 [TabGroup("MyGroup", "Tab1")] public int dataInMyGroupTab1; [TabGroup("MyGroup", "Tab2")] public int dataInMyGroupTab2; // 水平布局,不要超过2个,会有问题, [HorizontalGroup("HGroup")] public bool data1InHGroup