今回は、前々回の記事で少しだけでてきましたEditor拡張について少しかいてみます。
Editor拡張とは
UnityEditor内のみで動く(プレイヤーではなく、作り手側の使う)スクリプトを作って、UIや機能を改造、処理を自動化していくことを言うようです。
たとえば、ボタンを押したら外部のテキストファイルを読みにいって、そこにリストされたFBXファイルのパスから、FBXファイルをプロジェクトに自動コピー、インポート設定をして、インポート。とか
インポートしたときに自動でマテリアル設定をしてみたり・・・などなど便利になる機能が色々と考えられます。
Editor拡張のキモになる部分は、UnityEditorのGUI上で行う操作をスクリプトで呼べることです。それとC#で使える処理や、ウィンドウズ標準の機能などを組み合わせることで便利な自動化を実現できます。
使い方サンプル ウィンドウを出す
Assets/EditorにスクリプトをいれることでEditor内でのみ動くスクリプトとして認識されます。 以下のコードをButtonSample.csとしてAssets/Editorにいれてみてください。そうするとUnityのメインウィンドウメニューのWindowにButtonSampleの項目が追加されているはずです。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; // エディタ拡張関連はUnityEditor名前空間に定義されているのでusingしておく。
//ここはEditorWindowクラスを継承
public class ButtonSample : EditorWindow
{
// メニューのWindowにButtonSampleという項目を追加。
[MenuItem("Window/ButtonSample")]
static void Open()
{
EditorWindow.GetWindow("ButtonSample"); // タイトル名
}
void OnGUI()
{
// ボタンフラグ
bool Buttonflag;
// ラベルを表示
EditorGUILayout.LabelField("なにかおこすボタン");
Buttonflag = GUILayout.Button("Reload");
if (Buttonflag)
{
//OKCancelダイアログを表示
bool isOK = EditorUtility.DisplayDialog("Warning!", "ぼたんおされたやで" , "OK", "Cancel");
//OKCancelダイアログの戻り値を表示
Debug.Log(isOK);
}
}
}
クリックすると、OKCancelダイアログが表示されて、押したボタンによってConsoleビューに結果を返すシンプルなコードです。下の機能からの逆引きをコピペするなどして、ボタンを押したら色々動作するようにして遊んでいってください。
なお、こういった使い方以外にも、ゲームスクリプトにEditor時にだけ動作するように埋め込んでおくなどの使い方もできるようです。それはまた別の機会に。
機能からの逆引き
ちょろっとだけ書いてみます。
シーンファイルを開く
ファイルパスから、シーンを取得して開きます
//シーンファイルへのパス
string scenepath = Application.dataPath + "/Scenes/scene01.unity";
//パスからシーンファイルを取得
UnityEngine.SceneManagement.Scene scene = EditorSceneManager.GetSceneByPath(scenepath);
//シーンを開く
EditorSceneManager.OpenScene(scenepath);
プレハブを、シーンにドラッグ&ドロップをEditor拡張で
Projectビューにあるプレハブを、HierarchyまたはSceneビューにドラッグ&ドロップすると、シーンにプレハブが呼び出せます。これをスクリプト化すると以下のようになります。
//プレハブをゲームオブジェクトとしてスクリプトへ読む(Resrouces.Loadでも可。ただし書き方それぞれ違うので注意)
GameObject pPrefab = AssetDatabase.LoadAssetAtPath("Assets/vertextest.prefab", typeof(GameObject)) as GameObject;
//プレハブをシーンに配置
PrefabUtility.InstantiatePrefab(pPrefab);
なお、ランタイムで行うInstantiate関数と違い、インスタンス化しているわけではないので、GUIからドラッグしてインスタンス化したときと同じプレハブ状態になります。そのため、オブジェクト名に(Clone)と付きません。
余談ですが、LoadAssetAtPathは、Editor上でアセットをスクリプトに読み込むときには汎用的に使うものになります。PrefabのみならずAnimatorControllerなどProjectビューに表示されているものなら型変換すれば、なんでも読めるはずです。
アセットのインポートをEditor拡張で
ファイルをエクスプローラからUnityのProjectビューにドラッグしたり、エクスプローラでディレクトリへコピーしてUnityに戻ると自動でインポートされるあの処理です。スクリプトで外部からコピーしてきたファイルはそのままではインポートされない(UnityのProjectビューに表示されない)のでインポート処理を強制的に呼び出さないといけないのです。
AssetDatabase.ImportAsset("Assets/FBX/data.FBX", ImportAssetOptions.Default);
この処理の前に、C#のFileクラスなどでファイルをAssets以下にコピーしている前提です。
アセットのコピーをEditor拡張で
Projectビューでアセットを選択して、Ctrl+dを押すとアセットが複製できます。これを実現するコードは以下です。
AssetDatabase.CopyAsset("Assets/Scenes.controller", "Assets/Scenes2.controller");
外部からファイルをコピーの際ははやむを得ませんが、Assetsフォルダ内部での移動やコピーなどファイル・フォルダ管理はC#のFileクラスなどを使用せず、AssetDatabaseクラスの処理を使用してください。内部ファイル(metaファイル)がコピーされないなどの理由でプロジェクト自体がぶっこわれる可能性があるようです。これは、エクスプローラを使ってAssets内でファイル移動やコピーを行うとぶっこわれることがあるので、それと同じことです。
インポート設定の変更をEditor拡張で
インポート時ではなく、すでに読み終わっているアセットに対してインポート設定を変更する処理です。
//すでにあるアセット(この場合はModel)の読み込み設定をパスから取得
ModelImporter ModelImporter = AssetImporter.GetAtPath(tofilepath) as ModelImporter;
//リサンプルカーブをオフ
ModelImporter.resampleCurves = false;
//アニメーション圧縮をオフ
ModelImporter.animationCompression = ModelImporterAnimationCompression.Off;
//変更をApply
ModelImporter.SaveAndReimport();
この例はFBXなどのモデルアセットに対してですが、オーディオやテクスチャアセットに対して行う場合はこの記事をご参照ください。
アニメーターコントローラを新規作成をEditor拡張で
Projectビューで右クリック、Create>Animator Controller。この処理をスクリプトで実行してみます。
Assets内のパスを指定してその場所に新しいアニメータコントローラを作成します。
//Controllerを新規作成
var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/animcontroller.controller");
OKキャンセルダイアログを出すをEditor拡張で
よくあるOKCancelダイアログを出します。
//OKキャンセルダイアログをだす
bool isOK = EditorUtility.DisplayDialog("Warning!", "OKキャンセルダイアログの!\nサンプル" , "OK", "Cancel");
戻り値にはユーザーが押した結果が返っています。
コピーしようとしたらすでに同じファイルがあった、など色々なところで使用することができます。勝手に上書きや消すような処理は避け、できるだけこういったダイアログを出しましょう。
さいごに
まだまだ山のように機能はありますので、上で使用したクラスAssetDataBaseなどから機能を検索していったりしてください。また、間違っている点やご指摘、ご質問などございましたらコメントいただけると幸いです。