Help us understand the problem. What is going on with this article?

【Unity】スクリプトを生成してGameObjectにアタッチするまで自動化する

More than 1 year has passed since last update.

環境

OSX 10.11.6
Unity 5.4.2

やりたいこと

  1. テンプレートからスクリプトを生成
  2. 空のGameObjectを生成してスクリプトをアタッチ
  3. プレハブ化

これらを全部自動でやってほしい。

テンプレートの準備

まず、生成するスクリプトの元となるテンプレートを用意する。

CustomTemplate.txt
using UnityEngine;

public class #SCRIPTNAME# : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("#SCRIPTNAME#");
    }
}

テンプレート内の文字列"#SCRIPTNAME#"はスクリプト名に置換される場所とする。

スクリプト生成からプレハブ化まで

このテキストファイルをStreamReaderで読み込んで置換、csファイルとして保存する。

CreateScript.cs
static string templatePath = "テンプレートファイルのパス";
static string scriptName = "スクリプト名";

static void CreateNewScript()
{
    // テンプレートを読み込んでtempに格納
    StreamReader reader = new StreamReader(templatePath, Encoding.GetEncoding("Shift_JIS"));
    string template = reader.ReadToEnd();
    reader.Close();

    // テンプレート中の文字列"#SCRIPTNAME#"をスクリプト名に置換
    string scriptText = template.Replace("#SCRIPTNAME#", scriptName);

    // csファイルとしてScriptsフォルダに保存
    File.WriteAllText("Assets/Scripts/" + scriptName + ".cs", scriptText, Encoding.UTF8);

    AssetDatabase.Refresh();
}

スクリプトを生成した後、コンパイルが走る。
コンパイル終了後に空のGameObjectを生成して生成したスクリプトをアタッチしたいのだが、これが少し厄介。
コンパイルが終わったら処理が終了してしまい変数を保持できないため、必要な情報を外に出しておく必要がある。
今回の場合、Unity終了時に自動的に削除されるTempフォルダの中に一時ファイルとして保存することにした。

CreateScript.cs
static string tempFilePath = "Temp/一時ファイル名";

static void CreateTempFile()
{
    // 一時ファイルを生成し、必要な情報(ここではスクリプト名のみ)を書き込んで保存
    File.WriteAllText(tempFilePath, scriptName, Encoding.UTF8);
}

[DidReloadScripts]
static void OnCompiled()
{
    // 一時ファイルがあれば処理
    if (File.Exists(tempFilePath)) {
        StreamReader reader = new StreamReader(tempFilePath, Encoding.GetEncoding("Shift_JIS"));

        // スクリプト名を読み込み
        scriptName = reader.ReadLine();

        reader.Close();

        // 空のGameObjectを生成してスクリプトをアタッチし、プレハブ化(後述)
        CreateAttachedPrefab();

        // 一時ファイルの削除
        File.Delete(tempFilePath);
    }
}

DidReloadScriptsアトリビュートが設定されたメソッドは、再コンパイル後に自動的に実行される。
コンパイルが正常に終了すれば生成したスクリプトをアタッチできるようになるので、続けてこれをアタッチしたGameObjectを生成してプレハブ化する。

CreateScript.cs
static void CreateAttachedPrefab()
{
    // 空のGameObjectの生成
    GameObject go = new GameObject(scriptName);

    // 生成したスクリプトをアタッチ
    go.AddComponent(Type.GetType(scriptName));

    // プレハブの生成
    string prefabPath = "Assets/" + scriptName + ".prefab";
    GameObject prefab = PrefabUtility.CreatePrefab(prefabPath, go, ReplacePrefabOptions.ReplaceNameBased);
    go = PrefabUtility.ConnectGameObjectToPrefab(go, prefab);
}

EditorWindowで実行

これらの処理をGUIで実行できるようにEditorWindowとして作成する。
以下、全ソース。

CreateScript.cs
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System;
using System.IO;
using System.Text;

public class CreateScript : EditorWindow
{
    static string templatePath = "Assets/CustomTemplate.txt";
    static string scriptName = "NewScript";
    static string tempFilePath = "Temp/TempCreateScriptInfo";


    [MenuItem("Project/CreateScript")]
    static public void Open()
    {
        GetWindow<CreateScript>(true, "CreateScene");
    }

    private void OnGUI()
    {
        // コンパイル中は操作できないように
        EditorGUI.BeginDisabledGroup(EditorApplication.isCompiling);

        // スクリプト名を入力
        scriptName = EditorGUILayout.TextField("ScriptName", scriptName);

        // Createボタンを押してスクリプトと一時ファイルを生成し、ウィンドウを閉じる
        if (GUILayout.Button("Create")) {
            CreateNewScript();
            CreateTempFile();

            Close();
        }
        EditorGUI.EndDisabledGroup();
    }

    static void CreateNewScript()
    {
        // テンプレートを読み込んでtempに格納
        StreamReader reader = new StreamReader(templatePath, Encoding.GetEncoding("Shift_JIS"));
        string template = reader.ReadToEnd();
        reader.Close();

        // テンプレート中の文字列"#SCRIPTNAME#"をスクリプト名に置換
        string scriptText = template.Replace("#SCRIPTNAME#", scriptName);

        // csファイルとしてScriptsフォルダに保存
        File.WriteAllText("Assets/Scripts/" + scriptName + ".cs", scriptText, Encoding.UTF8);

        AssetDatabase.Refresh();
    }

    static void CreateTempFile()
    {
        // 一時ファイルを生成し、必要な情報(ここではスクリプト名のみ)を書き込んで保存
        File.WriteAllText(tempFilePath, scriptName, Encoding.UTF8);
    }

    [DidReloadScripts]
    static void OnCompiled()
    {
        // 一時ファイルがあれば処理
        if (File.Exists(tempFilePath)) {
            StreamReader reader = new StreamReader(tempFilePath, Encoding.GetEncoding("Shift_JIS"));

            // スクリプト名を読み込み
            scriptName = reader.ReadLine();

            reader.Close();

            // 空のGameObjectを生成してスクリプトをアタッチし、プレハブ化
            CreateAttachedPrefab();

            // 一時ファイルの削除
            File.Delete(tempFilePath);
        }
    }

    static void CreateAttachedPrefab()
    {
        // 空のGameObjectの生成
        GameObject go = new GameObject(scriptName);

        // 生成したスクリプトをアタッチ
        go.AddComponent(Type.GetType(scriptName));

        // プレハブの生成
        string prefabPath = "Assets/" + scriptName + ".prefab";
        GameObject prefab = PrefabUtility.CreatePrefab(prefabPath, go, ReplacePrefabOptions.ReplaceNameBased);
        go = PrefabUtility.ConnectGameObjectToPrefab(go, prefab);
    }
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした