Unity ScriptableObject

数据存储类ScriptableObject

不同与C#提供的Serializable序列化功能,ScriptableObject是Unity3D提供的一个数据存储类
优点:
ScriptableObject的数据是存储在asset里的,因此它不会在退出时被重置数据,这类似Unity里面的材质和纹理资源数据,我们在运行时刻改变它们的数值就是真的改变了
这些资源在实例化的时候是可以被引用,而非复制
类似其他资源,它可以被任何场景引用,即场景间共享
在项目之间共享
没有其他多余的东西,例如多余的Component
缺点:
很少的回调函数
OnEnable
OnDisable
OnDestroy

用例:
1.作为预制体共享数据例如子弹,每个子弹预制体上都有一个脚本,控制方向位置速度,还有一系列可调基础参数,但生成的每个预制体都会保存一份相同的数据,在优化方面来看无疑是一种浪费,所以这里使用 ScriptableObject 来保存共有的数据,它会被引用但只会有一份数据。
2.作为配置数据来使用,比如我要自动拆分aseprite的文件,一个项目我可以配置好导出路径,导出格式,拆分块大小,然后作为自动拆分aseprite生成动画的配置表。

生成ScriptableObject
通过菜单命令生成

[CreateAssetMenu(menuName = "MyConfigTool/CreatConfig")]
public class config : ScriptableObject
{
    public int myIntValue = 0;
    [Range(0,2.0f)]
    public float myFloatValue = 1.0f;
    
}

通过脚本生成
ScriptableObject.CreateInstance<config >();
这会在内存中创建一个新的实例,用作临时修改等用途,然后在不使用的时候可以让GC回收。
使用ScriptableObject
在生成或者获取到 scriptableObject对象后,直接访问调用

    private config cg;
    public config cg2;
    private void Awake()
    {
        cg = ScriptableObject.CreateInstance<config>();
    }

    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            Debug.Log(cg.myIntValue);
            Debug.Log(cg.myFloatValue);
            Debug.Log(cg2.myIntValue);
            Debug.Log(cg2.myFloatValue);
        }         
        if (Input.GetKeyDown(KeyCode.S))
        {
            cg.myIntValue += 1;
            cg.myFloatValue += 0.1f;
            cg2.myIntValue += 1;
            cg2.myFloatValue += 0.1f;
            Debug.Log(cg.myIntValue);
            Debug.Log(cg.myFloatValue);
            Debug.Log(cg2.myIntValue);
            Debug.Log(cg2.myFloatValue);
        }         

    }
image.png

脚本化导入器 Scripted Importer

应通过专门定义抽象类 ScriptedImporter 并应用 ScriptedImporter 属性来创建自定义导入器。这样会注册您的自定义导入器以处理一个或多个文件扩展名。当资源管线检测到一个与注册的文件扩展名匹配的文件为新文件或已更改的文件时,Unity 会调用自定义导入器的 OnImportAsset 方法

应用 对导入项目的asesprite工程文件做拆分自动绑定动画处理

#if SCRIPTABLE_IMPORTERS
[ScriptedImporter(1, new[] { "ase", "aseprite" })]
public class ASEImporter : ScriptedImporter {

    public ImportSettings settings;

    public override void OnImportAsset(AssetImportContext ctx) {
       //skip
    }
}
#endif

注意

  • 导入器在Unity的资源管线中注册,是通过在ASEImporter类上放置ScriptedImporter属性。
  • ASEImporter类实现了抽象的 ScriptedImporter 基类。
  • OnImportAsset 的 ctx 参数包含导入事件的输入和输出数据。
  • 每个导入事件必须生成对 SetMainAsset 的一次(且仅一次)调用。
  • 每个导入事件可以根据需要生成对 AddSubAsset 的任意次调用。
  • 请参阅脚本 API 文档以了解更多详细信息。

类似于我们在美观和可操作性方面对属性面板的优化 脚本话导入器我们也可以实现自定义,通过继承ScriptedImporterEditor类并使用Customer 类属性对其进行修饰以告知其用于哪种类型的导入器

[CustomEditor(typeof(ASEImporter))]
    public class ASEImporterEditor : ScriptedImporterEditor {
        public override void OnInspectorGUI() {
            // EditorGUILayout.LabelField("Hello?");
            base.OnInspectorGUI();

            var importer = (ASEImporter) target;
            GUI.enabled = importer.settings;
            EditorGUILayout.BeginHorizontal();

            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Import", GUILayout.Width(50))) {
                ASEImportProcess.Startup();
                ASEImportProcess.Import(importer.assetPath, importer.settings);
            }

            EditorGUILayout.EndHorizontal();
        }
    }

使用 Scripted Importer
将 Scripted Importer 类添加到项目后,可以像使用 Unity 支持的任何其他本机文件类型一样使用它:

  • 将一个受支持文件拖放到资源目录层级视图中可导入该文件。
  • 重新启动 Unity Editor 会重新导入自上次更新以来发生更改的所有文件。
  • 在磁盘上编辑资源文件并返回 Unity Editor 会触发重新导入。
  • 使用 Asset > Import New Asset… 导入新资源。
  • 通过菜单 Asset > Reimport 显式触发重新导入。
  • 单击资源可在 Inspector 窗口中查看其设置。要修改其设置,请在 Inspector 窗口中编辑这些设置,然后单击 Apply
    image.png

资源处理器 AssetPostprocessor

AssetPostprocessor是一个编辑器器类,需放置在Assets/Editor目录下使用,由于是编辑器类,所以引用using UnityEdirot
作用是在资源导入之前和之后可以根据导入的资源做一些设置和一些数据的修改,比如网格,纹理的压缩,模型添加组件等。当资源导入之前和之后都会发送通知,可以根据不同的资源类型,在导入之前和之后做不同的处理
函数有

OnPreprocessTexture
在子类中重载这个函数以便在纹理导入器运行之前获取通知

OnPostprocessTexture
在子类中加入这个函数,以便在纹理载入存入磁盘之前获得一个通知。

OnPreprocessModel
在子类中加入这个函数,以便在模型载入之前获得一个通知。

OnPostprocessModel
在子类中加入这个函数,以便在模型载入之后获得一个通知。

OnPostprocessGameObjectW...
在导入文件中,为每个至少附加了一个用户属性的游戏物体调用。

OnAssignMaterialModel
获取一个源材质

OnPostprocessAudio
在子类中加入这个函数,以便在一个声音剪辑载入后获得一个通知。

OnPreprocessAudio
在子类中加入这个函数,以便在一个声音剪辑载入之前获得一个通知。

OnPostprocessAllAssets
在一些资源被导入后调用(当资源进度条到达末端),所有资源的导入、删除、移动都会调用此方法,这个方法是`static`的
public static void OnPostprocessAllAssets(string[]importedAsset,string[] deletedAssets,string[] movedAssets,string[]movedFromAssetPaths)
{
}

internal 访问权限限制在程序集之内。针对程序集的,程序集中的任何类都是可以访问internal修饰的类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容