(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

エディタ拡張でオブジェクトを生成した場合にシーンを保存する方法【Unity】【エディタ拡張】


このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 5.6.1f1


はじめに

例えば以下のようなコードで、オブジェクトを生成するエディタ拡張を作る事が出来ますが、

using UnityEngine;
using UnityEditor;

public class GameObjectCreator {

  [MenuItem("Test/Create")]
  public static void Create (){
    //新しいゲームオブジェクトを作成
    new GameObject("New GameObject");
  }

}

f:id:kan_kikuchi:20170616064914g:plain


このコードだと、Sceneに編集済みのマーク(米印)が表示されず、保存する事が出来ません。


今回はそんな時に役立つ記事です。


Undo

Sceneが編集済みと認識されていないのは、変更点が記録がされていないからです。

なので、Undoクラスを使って、変更点を記録すれば解決出来ます。



今回のように、新しくオブジェクトを生成した時用の

RegisterCreatedObjectUndoというメソッドがあるので、

これを以下のような感じで使えば、

Sceneに編集済みのマークが表示され、保存する事が出来るようになります。

using UnityEngine;
using UnityEditor;

public class GameObjectCreator {

  [MenuItem("Test/Create")]
  public static void Create (){
    //新しいゲームオブジェクトを作成、その事をUndoに記録
    GameObject newGameObject = new GameObject("New GameObject");
    Undo.RegisterCreatedObjectUndo(newGameObject, "Create New GameObject");
  }

}

f:id:kan_kikuchi:20170616065921g:plain


また、⌘Zで元に戻す(Undo)事も出来るようになります。


f:id:kan_kikuchi:20170616065911p:plain


RegisterCreatedObjectUndo以外にも

プロパティーを修正した事を記録するUndo.RecordObject(s)

//gameObjectの座標を変更した事を記録(変更前に記録を開始する)
Undo.RecordObject (gameObject.transform, "Zero Transform Position");

gameObject.transform.position = Vector3.zero;

//gameObjectの全ての子の座標を変更した事を記録(変更前に記録を開始する)
Undo.RecordObjects(gameObject.GetComponentsInChildren<Transform>(), "Change Transform Position");

foreach (Transform childTransform in gameObject.transform) {
  childTransform.localPosition = Vector3.zero;
}


コンポーネントを追加した事を記録するUndo.AddComponent

//コンポーネントをアタッチし、その変更を記録
RigidBody rigidBody = Undo.AddComponent<RigidBody> (gameObject);


ゲームオブジェクトやコンポーネントを破棄した事を記録するUndo.DestroyObjectImmediate

//gameObjectにアタッチされているRigidBodyを破棄し、その変更を記録
Undo.DestroyObjectImmediate (gameObject.GetComponent<RigidBody>());

//gameObjectを破棄し、その変更を記録
Undo.DestroyObjectImmediate (gameObject);


親の変更を記録するUndo.SetTransformParentなどがあります。

//gameObjectの親をparentに変更し、その変更を記録
Undo.SetTransformParent (gameObject.transform, parent);


余談ですが、Sceneの保存まで自動でしたい場合はEditorSceneManager.SaveOpenScenesを使います。

using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;

public class GameObjectCreator {

  [MenuItem("Test/Create")]
  public static void Create (){
    //新しいゲームオブジェクトを作成、その事をUndoに記録
    GameObject newGameObject = new GameObject("New GameObject");
    Undo.RegisterCreatedObjectUndo(newGameObject, "Create New GameObject");

    //開いているシーンを全て保存(前もってUndoに記録していない部分は保存されない)
    EditorSceneManager.SaveOpenScenes();
  }

}


なお、SaveCurrentModifiedScenesIfUserWantsTo

使えば保存する前に確認のポップアップを出す事も可能です。


f:id:kan_kikuchi:20170616071232p:plain