You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity自定义Inspector开发:PlayerInventory类编辑器实现需求

嘿,我来帮你搞定这个Unity自定义Inspector的需求!针对你给出的ItemInventoryItem结构,我们可以用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.HeightGUILayout.Width的值,来改变预览图的大小。

内容的提问来源于stack exchange,提问作者Ben Rubin

火山引擎 最新活动