0
点赞
收藏
分享

微信扫一扫

Unity中的ScriptableObject

yellowone 2024-02-27 阅读 8

定义

这是Unity3D中一种特殊的对象类型,其独立于游戏对象存在,能够进行序列化和创建为资产,与Monobehaviour的派生类组件类似,但是ScriptableObject类型无法像组件一样挂载在游戏对象上。

常见应用场景

1.存储和管理可共享数据或资源(持久化存储);

2.编辑器工具(访问编辑器API);

3.事件系统(全局性资产);

4.数据序列化(可序列化);

5.可扩展性要求(可插拔)。

……

来自官方英文文档

个人使用总结

1.当在ScriptableObject派生类中通过自定义的方式实现单例模式时,在类内部访问成员字段或属性时,需要注意,通过单例访问和直接访问的区别。单例由于是静态的,所以全局保留在内存中,所以单例访问会贯穿整个生命周期,不会被GC回收,但是如果是直接访问则是一种类似于通过"this."的实例方式访问,这种方式会受到GC回收的影响,一旦当前派生类被禁用或不被外部访问时,GC就会回收该实例,在此之后,如果在类的内部通过直接访问的方式二次访问成员字段或属性,则会出现字段或属性为类型默认值(0或Null等)的情况,要避免这种情况要么当该类重新激活时进行初始化或者直接使用单例访问的方式。

2.ScriptableObject派生类适用于编辑器模式的资源修改和保存,不适用于运行时模式数据的持久化存储,例如对于一些辅助开发工具或者固定数据的持久化存储需求。

示例

通过ScriptableObject+CustomEditor实现通过Inspector面板在指定路径生成默认角色设置(Player Settings)的Json文件。

PlayerSettingsUnit.cs

using System;
using UnityEngine;

// 角色设置单元
[Serializable]
public class PlayerSettingsUnit
{
    [Tooltip("角色设置单元的键")]
    public string key;

    [Tooltip("角色设置单元的值")]
    public float value;

    public PlayerSettingsUnit() { }

    public PlayerSettingsUnit(string key, float value)
    {
        this.key = key;
        this.value = value;
    }

    public override string ToString()
    {
        return $"[key:{key},value:{value}]";
    }
}

PlayerSettingsDB.cs

using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

/// <summary>
/// 角色设置存储库
/// </summary>
[CreateAssetMenu(fileName = "Assets/Resources/DBs/PlayerSettingsDB.asset", menuName = "Custom/Create PlayerSettingsDB Asset", order = 1)]
public class PlayerSettingsDB : ScriptableObject
{
    [Header("角色设置单元集合(默认值)")]
    public PlayerSettingsUnit[] PlayerSettingsUnits;

    [Header("必要属性")]
    [SerializeField] private string filePath;
}

/// <summary>
/// 角色设置存储库自定义编辑器
/// </summary>
[CustomEditor(typeof(PlayerSettingsDB))]
public class PlayerSettingsDBEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        SerializedProperty property = serializedObject.FindProperty("filePath");
        GUILayout.BeginHorizontal();

        if (GUILayout.Button("Select File"))
        {
            // 打开文件选择面板,让用户选择文件
            string selectedPath = EditorUtility.OpenFilePanel("Select File", Application.dataPath, "");
            if (!string.IsNullOrEmpty(selectedPath))
            {
                // 如果用户选择了文件,则更新文件路径
                property.stringValue = selectedPath;
                // 应用序列化对象的更改
                serializedObject.ApplyModifiedProperties();
                // 更新Unity Inspector面板显示
                GUI.FocusControl(null);
            }
        }

        if (GUILayout.Button("Generate Json File"))
        {
            PlayerSettingsDB db = target as PlayerSettingsDB;
            // 将角色设置存储库实例序列化为JSON字符串
            string v_jsonStr = JsonUtility.ToJson(db);
            // 若JSON字符串存在
            if (!string.IsNullOrEmpty(v_jsonStr))
            {
                // 打开指定文件路径的JSON文件并写入JSON字符串内容
                using (FileStream fs = File.Open(property.stringValue, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    byte[] v_bytes = Encoding.UTF8.GetBytes(v_jsonStr);
                    fs.Write(v_bytes, 0, v_bytes.Length);
                    fs.Flush();
                }
            }
        }
        GUILayout.EndHorizontal();
        EditorGUILayout.HelpBox("The asset is used to generate the default json file of player settings.", MessageType.Info);
    }
}

 PS:PlayerSettingsUnit作为角色设置单元的实体类;PlayerSettingsDB则作为角色设置存储库,用于存储角色设置单元;PlayerSettingsDBEditor则作为对PlayerSettingsDB在Inspector面板的GUI显示进行自定义的类。通过Project视图右键菜单Create-Custom-Create PlayerSettingsDB Asset即可创建下图所示的角色设置存储库的.asset文件。

角色设置存储库的.asset文件的Inspector面板显示

PS:PlayerSettingsUnits则是角色设置存储库中默认的角色设置单元集合,在Inspector面板中设置每个角色设置单元的默认值,通过直接输入或Select File选择待生成或写入的JSON文件路径,最后点击Generate Json File即可。

如果这篇文章对你有帮助,请给作者点个赞吧!  

举报

相关推荐

0 条评论