Unity MenuItem で呼び出した処理の Undo を実装する

前回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) を追加しました。

  1. ゲームオブジェクト生成する
  2. 指定されたゲームオブジェクトの下位に配置する
    (ない場合はシーン直下)
  3. undo の処理を登録する
    (その後、作ったゲームオブジェクトを選択状態にする)

まずは (3) の Undo.RegisterCreatedObjectUndo 関数の呼び出しをコメントアウトした状態で試してみましょう。

//Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);

MenuItem Attribute の第1引数 itemName にある通り、メニューバーにメニューアイテムが追加されているので、[GameObject]→[MyCategory]→[Custom Game Object]選択します。

Unity 公式サイトのサンプルコードによって追加されたメニューアイテムを選択します(ゲームオブジェクトは選択していません)

サンプルコードにある Custom Game Object がシーン直下に配置されました。
シーン直下に配置されたのは、上位となるゲームオブジェクトを選択しないでメニューを指示したからです。

Unity MenuItem 公式のサンプルコードで名前を付けたゲームオブジェクトがシーン直下に追加されました。

先ほど Undo の登録をしないようにコメントアウトしたため、 Ctrl+Z などで Undo 処理をしようとしても何も元には戻らず生成された「Custom Game Object」は残っています

メニューバー[GameObject] の配下のメニューアイテム群は、Hierarchy ウィンドウのコンテキストメニューと連動しています。
今度は、Hierarchy ウィンドウでシーンのゲームオブジェクトを選択した状態で右クリックし、Hierarchy ウィンドウのコンテキストメニューから [MyCategory]→[Custom Game Object]選択します。

Unity 公式サイトのサンプルコードによって追加されたメニューアイテムをHierarchyウィンドウでゲームオブジェクトを選択した状態で表示し選択します。

今度は Hierarchy ウィンドウで選択したゲームオブジェクトの下に追加されました。

Unity MenuItem 公式のサンプルコードで名前を付けたゲームオブジェクトが選択したゲームオブジェクトの下に追加されました。

Undo の登録処理はコメントアウトしているので、 Ctrl+Z などの Undo による処理の取り消しは行われませんでした。

続いて、先ほどコメントアウトした Undo の関数呼び出しを有効にして、同じく試します。

Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);

メニューを選択し Custom Game Object をシーンに作成した後、 Ctrl + Z で Undo を指示すると、 Custom Game Object が消え、シーンはメニューを選択する前の状態に戻りました

Unity MenuItem 公式のサンプルコードによる Undo 処理の動作の様子

Undo 関数の説明

今回サンプルで使われた Undo の関数は作成したゲームオブジェクトを取り消す処理でした。
Undo クラスの静的関数 RegisterCreatedObjectUndo新しくオブジェクトを生成することに対応する Undo 処理を登録します。

Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);

第1引数は、生成したゲームオブジェクトです。Undo の際に破棄される対象です。
第2引数は、 Undo の名称です。このサンプルならば “Create Custom Game Object” と表示されます。

Unity Undo の関数で指定した名前が Undo メニューアイテムに付加されています。

この Undo メニューを実行すると、先ほど紹介したとおり、第 1 引数で指定した、メニューによりシーンに追加された Custom Game Object破棄されます。

Undo の様々なアクションに対応した関数

公式サイトの Undo のページには、他にも様々なアクションに対する Undo の関数があります。
必要に応じて調べて使っていきましょう。

Static 関数

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 操作を記録します
https://docs.unity3d.com/ja/2018.4/ScriptReference/Undo.html

まとめ

今回は MenuItem で追加したメニューアイテムの処理を実行したあと Undo するための処理の例を紹介しました。
様々なアクションに対応した関数が用意されているので、ケースによって使い分けましょう。

参照サイト Thank You!

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました