topaz-dev’s

ああああああ

連番のスクリプタブルオブジェクト

連番でスクリプタブルオブジェクトを生成する。

ディレクトリに存在するアセットの数を確認してインクリメントした名前のスクリプタブルオブジェクトを生成する。 CreateInstanceで生成したインスタンスは別の名前で新しくスクリプタブルオブジェクトを生成することができないため、一度スクリプタブルオブジェクトを生成したら新しくインスタンスを生成しなくてはならない。

youtu.be

public class SOGeneratorWindow : EditorWindow
{
    // スクリプタブルオブジェクト生成用のウィンドウを表示する
    [MenuItem("MyWindow/Open")]
    public static void ShowWindow()
    {
        SOGeneratorWindow window = EditorWindow.GetWindow<SOGeneratorWindow>();
        window.Show();

    }

    // 別で作成したスクリプタブルオブジェクトを継承したクラス
    private CharaParam _charaParam;
    private void OnGUI()
    {
        if (_charaParam == null) _charaParam = CreateInstance<CharaParam>();

        // ここからパラメタを設定するためのフィールドを表示する
        using (var h = new EditorGUILayout.HorizontalScope())
        {
            EditorGUILayout.LabelField("名前", GUILayout.Width(50));
            _charaParam._name = EditorGUILayout.TextField(_charaParam._name);
        }
        using (var h = new EditorGUILayout.HorizontalScope())
        {
            EditorGUILayout.LabelField("最大HP", GUILayout.Width(50));
            _charaParam._maxHP = EditorGUILayout.IntField(_charaParam._maxHP);
        }
        using (var h = new EditorGUILayout.HorizontalScope())
        {
            EditorGUILayout.LabelField("スピード", GUILayout.Width(50));
            _charaParam._speed = EditorGUILayout.IntField(_charaParam._speed);
        }



         // ここからスクリプタブルオブジェクトを生成するボタンを表示する。
        using (var h = new GUILayout.HorizontalScope())
        {
            if (GUILayout.Button("スクリプタブルオブジェクトを作成する"))
            {
                Debug.LogWarning("作成します");
                CreateSOParam();
            }
            if (GUILayout.Button("リセット", GUILayout.MaxWidth(30)))
            {
                ResetInstance();
            }
        }
    }

    // スクリプタブルオブジェクトを生成する
    private void CreateSOParam()
    {
        // Assets以下のpathを指定する
        var path = "/Data/CharaParam";
        // Application.dataPath : プロジェクトのパス/Assets
        var dir = Application.dataPath + path;  
        // ディレクトリがなければ生成する
        if (!Directory.Exists(dir))
        {
            Debug.LogWarning("ディレクトリを生成します");
            var info = Directory.CreateDirectory(dir);
            AssetDatabase.Refresh();
        }
        // 現在生成されているスクリプタブルオブジェクトの数を数える
        int cnt = Directory.GetFiles(dir)
                    .Where(name => name.Substring(name.Length - 4).Equals("meta"))
                    .Count();
         // 新しく作るスクリプタブルオブジェクトの名前(番号)を決定する
        var fileName = "CharaParam" + String.Format("{0:0000}", cnt + 1);
        // .asset拡張子として生成する
        AssetDatabase.CreateAsset(_charaParam, "Assets" + path + "/" + fileName + ".asset");
        ResetInstance();
        // 生成を反映する
        AssetDatabase.Refresh();
    }
    // 新しくインスタンスを生成する。現在の値をコピーしておく。
    private void ResetInstance()
    {
        var tmp = _charaParam;
        _charaParam = CreateInstance<CharaParam>();
        _charaParam._name = tmp._name;
        _charaParam._maxHP = tmp._maxHP;
        _charaParam._speed = tmp._speed;

    }
}
まとめ

fileNameの部分を変えることで、好きな名前のスクリプタブルオブジェクトを生成することができる。

特定のシーンから開始する

指定したシーンをロードして開始する。

EditorSceneManagerの開始シーンを設定することで開始シーンを指定する。EnterPlaymodeで再生シーンに移動する。IsPlayingをtureにしても同じ結果となる。

public void ToPlayMode(){
    string path = "Assets/Scenes/SampleScene.unity";
    SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(path);
    EditorSceneManager.playModeStartScene = sceneAsset;
    EditorApplication.EnterPlaymode();

GUILayoutoption

Unityのエディタ拡張をリファレンスを見ているとよく出てくるparams GUILayoutOption[] optionsの引数。色々指定できて便利なのでできることをざっとメモ。指定しなくても平気なパラメタだから拘らなければ使う必要は全くない。

// このような形で出てくる。
public static void LabelField(string label, params GUILayoutOption[] options);

出来ること

GUILayoutOptionを指定することで、EditorGUILayoutやGUILayoutを使っていい感じにUnityに描画サイズを決めてもらう時のサイズを変更することが出来る。

GUILayoutOptionの生成方法

公式のリファレンスによると「直接GUILayoutOptionを作成しないで、GUILayoutのstatic関数から生成してくれ!」と書いてある。言われた通りにしておきましょう。使用できる関数は、GUILayout.Width, GUILayout.Height, GUILayout.MinWidth, GUILayout.MaxWidth, GUILayout.MinHeight, GUILayout.MaxHeight, GUILayout.ExpandWidth, GUILayout.ExpandHeight。となっていて、横幅系4つと縦幅系4つになっている。

使用方法

GUILayoutOptionはparamsを用いた可変長引数で定義されているので、引数に入れたい分だけ羅列していけば良い。可変長引数について分からなければ、未確認飛行Cのサイトがとてもわかりやすくて助かる。
見た目的に囲われてわかりやすいボタンで書いてみる。

        if (GUILayout.Button("height 70のボタン", GUILayout.Height(70)))
        {// 高さの変更
        }
        if (GUILayout.Button("width 200のボタン", GUILayout.Width(200)))
        {// 横幅の変更
        }
        if (GUILayout.Button("width 200,height 70のボタン", GUILayout.Width(200), GUILayout.Height(70)))
        {// 高さと横幅の変更
        }
        if (GUILayout.Button("width 200,800,400のボタン", GUILayout.Width(200), GUILayout.Width(800), GUILayout.Width(400)))
        {// 同じパラメタを設定した場合は最後に指定した値(400)が適用される
        }

表示してみると確かにWidthHeightが適用されていることが分かる。この二つのパラメタは確かに使えそうだと分かったが、MInMax Expandがまだ存在する。またGUILayoutの機能を使っているため要素は縦に並んでいくようになっている。

ボタンなどの要素を横に並べるためにはEditorGUILayout.HorizontalScope()を使えばよい。昔はBeginHorizontalEndHorizontalという関数が使われていたらしい。。。使い方はusingステートメントを使用してブロック内に横に並べたい要素を書いていきます。

        using (var w = new EditorGUILayout.HorizontalScope())
        {
            if (GUILayout.Button("ボタン1"))
            {
            }
            if (GUILayout.Button("ボタン2"))
            {
            }
        }

使用してみるとブロック内の要素数に応じて自動でボタンのサイズを調整してくれます。

ここでMInWidthを使用して左側のボタンの最小の横幅を指定します。これはウィンドウのサイズ自体が変化した時に効力を発揮する等になります。

    GUILayout.Button("ボタン1 : minwidth 200", GUILayout.MinWidth(200))


www.youtube.com

下に並んでいるボタンの左側のボタンだけにMinWidthを設定したんですが、なぜか最初のウィンドウの大きさでのWidthも変更されてしまっています。Unity側がいい感じに設定していそうなのですが、分かる方いましたら教えてください。

MaxWidthはそのままの意味で横幅の最大値を記載することができます。

最後のExpandWidthはデフォルトでtrueになっており、falseを設定することで文字の幅に合わせたサイズのボタンが生成されるようになっています。

        GUILayout.Button("expandWidth : false", GUILayout.ExpandWidth(false)))
        GUILayout.Button("expandWidth : false あああああああああああああああ", GUILayout.ExpandWidth(false)))

まとめ

GUILayoutOptionを使っていい感じの配置を作ることでかっこいいエディタを簡単に作れる。
文字の色などはGUIStyleを使ってさらにかっこよく出来る。今回のGUILayoutOptionはレイアウトを決めるためのものということを理解しておきたい。

UnityでFile操作する

ファイルの作成をする

ファイルを既に存在する場合新しく作ってしまうのでファイルが存在するかを確認する必要がある。

// targetPathには拡張子(.txt)なども含める。
string targetPath = Application.dataPath + "/" + path + "/" + fileName;

if (File.Exists(targetPath))
{
    Debug.LogWarning($"{targetPath} は存在します");
    // ファイルが存在する場合新しく空のファイルを生成してしまう。
    // File.Create(targetPath);
}
else
{
    Debug.LogWarning($"{targetPath} は存在しません");
     File.Create(targetPath);
}

// データベースを更新する
AssetDatabase.Refresh();