表題の通りです。
1. 概要
UnityのScene内に存在するすべてのGameObjectの表示状態(activeSelf
)を保存し、あとから復元できるエディタ拡張ツールです。
- SnapShotボタン:現在の表示状態を保存
- Resumeボタン:保存された状態を復元
- Unityの再起動後は
instanceID
が無効になるため、名前階層(path)で探索し復元
(一度復元したあとは自動でSnapShot
を再保存し、次回からは高速に復元可能)
2. スクリプト本体
Assets/Editor/VisibilitySnapshot.cs
に以下のコードを配置してください:
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
/// <summary>
/// Unityでヒエラルキーのオブジェクト全てのActive状態を保存・再生するエディタ拡張
/// </summary>
/// instanceIDが無くなった時だけパスでFindする。それ以外はinstanceIDで取得する。
public class VisibilitySnapshot : EditorWindow
{
private const string FILE_PATH = "Library/VisibilitySnapshot.json";
[System.Serializable]
private class Entry
{
public int id;
public string path;
public bool active;
}
[System.Serializable]
private class EntryList
{
public List<Entry> entries = new List<Entry>();
}
[MenuItem("Tools/Visibility Snapshot")]
public static void ShowWindow()
{
GetWindow<VisibilitySnapshot>("Visibility Snapshot");
}
private void OnGUI()
{
if (GUILayout.Button("SnapShot (Save to File)"))
{
SaveSnapshotToFile();
}
if (GUILayout.Button("Resume (Load from File)"))
{
LoadSnapshotFromFile();
}
}
private void SaveSnapshotToFile(bool _showMsg = true)
{
var list = new EntryList();
foreach (GameObject root in GetAllRootGameObjectsInScene())
{
RecordRecursive(root, "", list.entries);
}
string json = JsonUtility.ToJson(list, true);
File.WriteAllText(FILE_PATH, json);
Debug.Log($"スナップショットを保存しました ({list.entries.Count}件): {FILE_PATH}");
if (_showMsg)
{
EditorUtility.DisplayDialog("SnapShot完了", $"スナップショットを保存しました\n({list.entries.Count}件)", "OK");
}
}
private void LoadSnapshotFromFile()
{
if (!File.Exists(FILE_PATH))
{
Debug.LogWarning("スナップショットファイルが見つかりません。");
return;
}
string json = File.ReadAllText(FILE_PATH);
var list = JsonUtility.FromJson<EntryList>(json);
int changed = 0;
bool foundPath = false;
foreach (var entry in list.entries)
{
GameObject obj = EditorUtility.InstanceIDToObject(entry.id) as GameObject;
if (obj == null)
{
// IDが無効なら、パスで探す
obj = GameObject.Find(entry.path);
foundPath = true;
}
if (obj != null && obj.activeSelf != entry.active)
{
obj.SetActive(entry.active);
changed++;
}
}
Debug.Log($"スナップショットを復元しました ({changed}件)");
// 復元したオブジェクトの中に、パスで見つけたものがあった場合は、次の高速化のために再度保存しておく
if (foundPath)
{
SaveSnapshotToFile(false);
}
}
private void RecordRecursive(GameObject obj, string parentPath, List<Entry> entries)
{
string path = string.IsNullOrEmpty(parentPath) ? obj.name : parentPath + "/" + obj.name;
entries.Add(new Entry
{
id = obj.GetInstanceID(),
path = path,
active = obj.activeSelf
});
foreach (Transform child in obj.transform)
{
RecordRecursive(child.gameObject, path, entries);
}
}
private GameObject[] GetAllRootGameObjectsInScene()
{
var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
return scene.GetRootGameObjects();
}
}
3. 導入手順
1.Unityエディタで Assets/Editor/ フォルダを作成(なければ)
2.下記スクリプトを作成:VisibilitySnapshot.cs
4. 使い方
① スナップショットの保存
Unity上部メニューから
Tools > Visibility Snapshot をクリック
表示されたウィンドウで
「SnapShot (Save to File)」をクリック
現在のScene内にあるすべてのGameObjectの「表示状態(activeSelf)」を記録します。
◆保存先ファイル:/Library/VisibilitySnapshot.json に出力されます。
② スナップショットの復元
再び Tools > Visibility Snapshot ウィンドウを開く
「Resume (Load from File)」をクリック
保存時と同じScene内であれば、
- InstanceIDベースで高速復元
- 見つからない場合は GameObjectの名前階層(Root/Child/...)で復元
(その場合次の高速化に備えてSaveも行う)
Sceneを再起動してもファイルが残っていれば復元可能です。
5. メリットと注意点
- Unityセッション中は高速
- 再起動後の初回復元は
GameObject.Find()
になるので少し遅い - ただし一度復元すれば、以後は再び
instanceID
を利用して高速化