前回は MenuItem のコンストラクタのツールヒントで出てきた各プロパティの検証と、自作クラスで同様のプロパティを出すコードを紹介しました。
今回は MenuItem で静的関数を呼び出して行ったアクションを取り消すための Undo 処理を実装する具体例を紹介します。
※ Unity は 2022.3.14.f1、Visual Studio は Community 2022 Version 17.2.5 です。
Undo System への登録
公式サイトにサンプルのコードがあるので、それを使ってみましょう。
// 参照 https://docs.unity3d.com/ja/2018.4/ScriptReference/MenuItem.html
// Add a menu item to create custom GameObjects.
// Priority 1 ensures it is grouped with the other menu items of the same kind
// and propagated to the hierarchy dropdown and hierarchy context menus.
[MenuItem("GameObject/MyCategory/Custom Game Object", false, 10)]
static void CreateCustomGameObject(MenuCommand menuCommand)
{
// (1) Create a custom game object
GameObject go = new GameObject("Custom Game Object");
// (2) Ensure it gets reparented if this was a context click (otherwise does nothing)
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
// (3) Register the creation in the undo system
Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
Selection.activeObject = go;
}
処理の流れは以下です。コードの処理のコメントに (1) ~ (3) を追加しました。
- ゲームオブジェクトを生成する
- 指定されたゲームオブジェクトの下位に配置する
(ない場合はシーン直下) - undo の処理を登録する
(その後、作ったゲームオブジェクトを選択状態にする)
まずは (3) の Undo.RegisterCreatedObjectUndo 関数の呼び出しをコメントアウトした状態で試してみましょう。
//Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
MenuItem Attribute の第1引数 itemName にある通り、メニューバーにメニューアイテムが追加されているので、[GameObject]→[MyCategory]→[Custom Game Object] を選択します。
サンプルコードにある Custom Game Object がシーン直下に配置されました。
シーン直下に配置されたのは、上位となるゲームオブジェクトを選択しないでメニューを指示したからです。
先ほど Undo の登録をしないようにコメントアウトしたため、 Ctrl+Z などで Undo 処理をしようとしても何も元には戻らず、生成された「Custom Game Object」は残っています。
メニューバー[GameObject] の配下のメニューアイテム群は、Hierarchy ウィンドウのコンテキストメニューと連動しています。
今度は、Hierarchy ウィンドウでシーンのゲームオブジェクトを選択した状態で右クリックし、Hierarchy ウィンドウのコンテキストメニューから [MyCategory]→[Custom Game Object] を選択します。
今度は Hierarchy ウィンドウで選択したゲームオブジェクトの下に追加されました。
Undo の登録処理はコメントアウトしているので、 Ctrl+Z などの Undo による処理の取り消しは行われませんでした。
続いて、先ほどコメントアウトした Undo の関数呼び出しを有効にして、同じく試します。
Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
メニューを選択し Custom Game Object をシーンに作成した後、 Ctrl + Z で Undo を指示すると、 Custom Game Object が消え、シーンはメニューを選択する前の状態に戻りました。
Undo 関数の説明
今回サンプルで使われた Undo の関数は作成したゲームオブジェクトを取り消す処理でした。
Undo クラスの静的関数 RegisterCreatedObjectUndo は新しくオブジェクトを生成することに対応する Undo 処理を登録します。
Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
第1引数は、生成したゲームオブジェクトです。Undo の際に破棄される対象です。
第2引数は、 Undo の名称です。このサンプルならば “Create Custom Game Object” と表示されます。
この Undo メニューを実行すると、先ほど紹介したとおり、第 1 引数で指定した、メニューによりシーンに追加された Custom Game Object が破棄されます。
Undo の様々なアクションに対応した関数
公式サイトの Undo のページには、他にも様々なアクションに対する Undo の関数があります。
必要に応じて調べて使っていきましょう。
Static 関数
https://docs.unity3d.com/ja/2018.4/ScriptReference/Undo.html
AddComponent ゲームオブジェクトにコンポーネントをアタッチし、その操作の Undo を登録します。 ClearAll Removes all undo and redo operations from respectively the undo and redo stacks. ClearUndo Undo.RegisterCompleteObjectUndo を使って登録した identifier オブジェクトへの Undo 操作をすべて、Undo スタックから削除します。 CollapseUndoOperations すべての Undo 操作を 1 つのステップにまとめます。 DestroyObjectImmediate オブジェクトを破棄し、Undo 操作によって復元できるように記録します。 FlushUndoRecordObjects RecordObject または ::ref:RecordObjects は Undo 可能なアクションとして記録されていることを確認してください。FlushUndoRecordObjects はマウスボタンを離し、通常、アクションをまとめるその他のイベントが終わった直後に自動的に行われるため、たいていは、わざわざ呼び出す必要はありません。 GetCurrentGroup Unity が自動的に Undo 操作をグループ化したもので現在のグループインデックスを取得します GetCurrentGroupName 現在の Undo グループの UI に表示される名前を取得します。 IncrementCurrentGroup Unity が自動的に Undo 操作をグループ化したもので現在のグループインデックスを取得します MoveGameObjectToScene Move a GameObject from its current Scene to a new Scene. It is required that the GameObject is at the root of its current Scene. PerformRedo Redo 操作を行います。 PerformUndo Undo 操作を行います。 RecordObject RecordObject が呼び出された後の変更点を記録します RecordObjects 1 回の呼び出しで複数の Undo 可能なオブジェクトを記録します。これは複数回 Undo.RecordObject を呼び出すのと同じです。 RegisterCompleteObjectUndo Undo スタック上のオブジェクトの状態の複製を保存します。 RegisterCreatedObjectUndo 新しくオブジェクトを生成するときの Undo 操作を登録します RegisterFullObjectHierarchyUndo オブジェクトのヒエラルキーの状態を Undo スタック上にコピーします。 RevertAllDownToGroup 処理中の Redo 操作を保存せずに、グループインデックスまでのすべての Undo 操作を行います。 RevertAllInCurrentGroup Undo 操作は実行されますが Redo 操作は行うことはできません SetCurrentGroupName 現在の Undo グループに名前をつける。 SetTransformParent 新しく Transform の親を設定し Undo 操作を記録します
まとめ
今回は MenuItem で追加したメニューアイテムの処理を実行したあと Undo するための処理の例を紹介しました。
様々なアクションに対応した関数が用意されているので、ケースによって使い分けましょう。
コメント