🙆

スクリプトからScriptableObjectを生成、アセットとして保存する

2021/09/25に公開

あらまし

サードパーティ製ライブラリインポート時にScriptableObject継承のアセットが自動生成されていたので、どういったメソッドを使ってアセットとして保存しているか気になったので記事に起こしてみた。

概要

以下の手順でScriptableObjectを生成、アセットとして保存する。

  • ScriptableObject.CreateInstance<T>() または ScriptableObject.CreateInstance(className) でScriptableObjectのインスタンスを生成
  • (必要であれば)対象のScriptableObjectの中身を書き換え
  • (必要であれば)保存先のディレクトリが存在するかチェックする(存在しなければ作成する)
  • AssetDatabase.CreateAsset(instance, fileName) でアセットとして保存する

サンプルコード

※下記のコードでは保存対象のファイルは常に上書きされるので、上書きを回避したい場合は別途その処理を書く必要がある。

SOGeneratorSample.cs
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

public class SOGeneratorSample
{
    [MenuItem("MyGenerator/CreateScriptableObject")]
    private static void CreateScriptableObject()
    {
        var obj = ScriptableObject.CreateInstance<MyScriptableObject>();
        obj.hogeValue = "hogehoge";
        var fileName = $"{TypeNameToString(obj.GetType().ToString())}.asset";
        var path = "Assets/MyFiles";
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);
        AssetDatabase.CreateAsset(obj, Path.Combine(path, fileName));
    }
    
    private static string TypeNameToString(string type)
    {
        var typeParts = type.Split(new char[] { '.' });
        if (!typeParts.Any())
            return string.Empty;

        var words = Regex.Matches(typeParts.Last(), "(^[a-z]+|[A-Z]+(?![a-z])|[A-Z][a-z]+)")
            .OfType<Match>()
            .Select(match => match.Value)
            .ToArray();
        return string.Join(" ", words);
    }
}
MyScriptableObject.cs
public class MyScriptableObject : ScriptableObject
{
    [SerializeField] private string m_HogeValue = "hoge";

    public string hogeValue
    {
        get => m_HogeValue;
        set => m_HogeValue = value;
    }
}

実行

メニューから処理を選択

指定したディレクトリにファイルが作られている

インスペクタを確認するとスクリプトで指定した内容を反映している

Discussion