You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在引用Scriptable Object的脚本检视器中查看并编辑其字段?

可行,实现方法如下

在Unity里完全可以做到不用选中ScriptableObject资源,直接在引用它的脚本检视器中编辑其字段,下面是两种常用的实现方式:

方法一:自定义PropertyDrawer(全局通用)

这种方式可以让所有标记了特定属性的ScriptableObject引用,都能在检视器中直接展开编辑内部字段,适用性广。

步骤1:定义自定义属性和ScriptableObject类

using UnityEngine;

// 标记需要内联编辑的ScriptableObject的属性
public class InlineScriptableObjectAttribute : PropertyAttribute { }

// 你的ScriptableObject示例类
[CreateAssetMenu(fileName = "NewData", menuName = "Custom/Data")]
public class MyScriptableObject : ScriptableObject
{
    public int myInt;
    public float myFloat;
    public string myString;
}

步骤2:编写PropertyDrawer实现内联绘制

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(InlineScriptableObjectAttribute))]
public class InlineScriptableObjectDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // 先绘制默认的ScriptableObject引用选择框
        EditorGUI.PropertyField(position, property, label);
        
        // 如果已有引用,展开绘制内部字段
        if (property.objectReferenceValue != null)
        {
            EditorGUI.indentLevel++;
            var serializedObj = new SerializedObject(property.objectReferenceValue);
            serializedObj.Update();
            
            // 遍历所有可序列化字段(跳过默认的m_Script字段)
            var iterator = serializedObj.GetIterator();
            if (iterator.NextVisible(true))
            {
                do
                {
                    position.y += EditorGUI.GetPropertyHeight(iterator);
                    EditorGUI.PropertyField(EditorGUI.IndentedRect(position), iterator);
                } while (iterator.NextVisible(false));
            }
            
            serializedObj.ApplyModifiedProperties();
            EditorGUI.indentLevel--;
        }
    }

    // 计算整个属性需要的高度(包含引用框和内部字段)
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        float height = EditorGUI.GetPropertyHeight(property, label);
        
        if (property.objectReferenceValue != null)
        {
            var serializedObj = new SerializedObject(property.objectReferenceValue);
            var iterator = serializedObj.GetIterator();
            if (iterator.NextVisible(true))
            {
                do
                {
                    height += EditorGUI.GetPropertyHeight(iterator);
                } while (iterator.NextVisible(false));
            }
        }
        
        return height;
    }
}

步骤3:在脚本中使用

在引用ScriptableObject的MonoBehaviour里,给字段加上自定义属性即可:

using UnityEngine;

public class TestScript : MonoBehaviour
{
    [InlineScriptableObject]
    public MyScriptableObject data;
}

方法二:自定义Editor(针对特定脚本)

如果只需要在某个特定的MonoBehaviour中实现内联编辑,直接写自定义Editor会更灵活,能精准控制要显示的字段。

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(TestScript))]
public class TestScriptEditor : Editor
{
    public override void OnInspectorGUI()
    {
        var targetScript = (TestScript)target;
        
        // 绘制ScriptableObject引用选择框
        targetScript.data = (MyScriptableObject)EditorGUILayout.ObjectField("数据对象", targetScript.data, typeof(MyScriptableObject), false);
        
        // 引用不为空时,绘制内部字段
        if (targetScript.data != null)
        {
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("内部字段", EditorStyles.boldLabel);
            
            EditorGUI.indentLevel++;
            targetScript.data.myInt = EditorGUILayout.IntField("整数", targetScript.data.myInt);
            targetScript.data.myFloat = EditorGUILayout.FloatField("浮点数", targetScript.data.myFloat);
            targetScript.data.myString = EditorGUILayout.TextField("字符串", targetScript.data.myString);
            EditorGUI.indentLevel--;
            
            // 标记资源已修改,确保修改能保存
            if (GUI.changed)
            {
                EditorUtility.SetDirty(targetScript.data);
            }
        }
    }
}

注意事项

  • 两种方式修改的都是ScriptableObject资源本身,所有引用该资源的脚本都会同步看到修改;
  • 使用SerializedObject的ApplyModifiedProperties或EditorUtility.SetDirty确保修改能保存到资源文件;
  • 可根据需求扩展PropertyDrawer的逻辑,比如添加折叠按钮、处理嵌套的可序列化对象等。

内容的提问来源于stack exchange,提问作者Fahim kamal Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:53:20