Unity自定义Inspector开发:PlayerInventory类编辑器实现需求
嘿,我来帮你搞定这个Unity自定义Inspector的需求!针对你给出的Item和InventoryItem结构,我们可以用Unity的Editor扩展系统来做一个直观好用的可视化编辑界面,下面是完整的实现步骤和代码:
核心实现思路
我们需要创建两个自定义Editor脚本:一个针对单个InventoryItem,用来优化它的Inspector显示(比如直接展示物品的描述和预览图);另一个如果你的PlayerInventory是包含多个InventoryItem的列表,就做一个批量编辑的界面,让物品栏的管理更高效。
步骤1:单个InventoryItem的自定义Inspector
首先创建一个名为InventoryItemEditor的脚本,必须放在项目的Editor文件夹下(不然打包时会报错):
using UnityEditor; using UnityEngine; [CustomEditor(typeof(InventoryItem))] [CanEditMultipleObjects] public class InventoryItemEditor : Editor { private SerializedProperty itemProp; private SerializedProperty quantityProp; private void OnEnable() { // 获取序列化属性,这样能自动支持Undo/Redo和多对象编辑 itemProp = serializedObject.FindProperty("item"); quantityProp = serializedObject.FindProperty("quantity"); } public override void OnInspectorGUI() { // 更新序列化对象,同步最新数据 serializedObject.Update(); // 绘制Item引用字段 EditorGUILayout.PropertyField(itemProp); // 如果选中了Item,就展示它的描述和预览图 Item selectedItem = itemProp.objectReferenceValue as Item; if (selectedItem != null) { EditorGUILayout.LabelField("物品描述", selectedItem.description); if (selectedItem.picture != null) { // 绘制物品预览图,尺寸可以自行调整 GUILayout.Label(selectedItem.picture, GUILayout.Height(64), GUILayout.Width(64)); } else { EditorGUILayout.HelpBox("这个物品还没设置预览图哦", MessageType.Warning); } } // 绘制数量字段,同时限制数量不能为负数 EditorGUILayout.PropertyField(quantityProp); if (quantityProp.intValue < 0) { quantityProp.intValue = 0; EditorGUILayout.HelpBox("物品数量不能是负数哦", MessageType.Error); } // 应用所有修改到对象上 serializedObject.ApplyModifiedProperties(); } }
步骤2:PlayerInventory的批量编辑界面(可选)
如果你的PlayerInventory类是类似下面这样的物品列表结构:
public class PlayerInventory : MonoBehaviour { public List<InventoryItem> inventoryItems = new List<InventoryItem>(); }
那我们可以再写一个PlayerInventoryEditor来优化列表的显示和操作:
using UnityEditor; using UnityEngine; [CustomEditor(typeof(PlayerInventory))] public class PlayerInventoryEditor : Editor { private SerializedProperty inventoryItemsProp; private void OnEnable() { inventoryItemsProp = serializedObject.FindProperty("inventoryItems"); } public override void OnInspectorGUI() { serializedObject.Update(); // 绘制标题 EditorGUILayout.LabelField("玩家物品栏", EditorStyles.boldLabel); // 遍历每个物品,显示预览和基本信息 for (int i = 0; i < inventoryItemsProp.arraySize; i++) { SerializedProperty itemElement = inventoryItemsProp.GetArrayElementAtIndex(i); InventoryItem invItem = itemElement.objectReferenceValue as InventoryItem; EditorGUILayout.BeginHorizontal(); // 显示物品预览图和信息 if (invItem != null && invItem.item != null) { if (invItem.item.picture != null) { GUILayout.Label(invItem.item.picture, GUILayout.Height(48), GUILayout.Width(48)); } EditorGUILayout.LabelField($"{invItem.item.description} (x{invItem.quantity})"); } else { EditorGUILayout.LabelField("未设置有效物品"); } // 删除按钮 if (GUILayout.Button("-", GUILayout.Width(24))) { inventoryItemsProp.DeleteArrayElementAtIndex(i); i--; // 删除后索引会前移,所以要减1避免跳过下一个物品 } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); } // 添加新物品的按钮 if (GUILayout.Button("添加新物品")) { // 创建新的InventoryItem实例 InventoryItem newInvItem = CreateInstance<InventoryItem>(); newInvItem.quantity = 1; // 默认数量设为1 // 添加到列表 inventoryItemsProp.arraySize++; inventoryItemsProp.GetArrayElementAtIndex(inventoryItemsProp.arraySize - 1).objectReferenceValue = newInvItem; // 保存到项目中,避免丢失 string assetPath = $"Assets/NewInventoryItem_{System.DateTime.Now.Ticks}.asset"; AssetDatabase.CreateAsset(newInvItem, assetPath); AssetDatabase.SaveAssets(); } serializedObject.ApplyModifiedProperties(); } }
一些实用的优化建议
- 多对象编辑:第一个脚本加了
[CanEditMultipleObjects]标签,你可以同时选中多个InventoryItem,批量修改数量或者替换物品,非常方便。 - 数据合法性检查:我们加了数量不能为负的限制,避免出现无效的库存数据。
- Undo/Redo支持:因为用了Unity的
SerializedProperty系统,所有修改都会自动支持Undo和Redo,不用额外写代码。 - 预览图自定义:你可以根据需求调整
GUILayout.Height和GUILayout.Width的值,来改变预览图的大小。
内容的提问来源于stack exchange,提问作者Ben Rubin




