UnityAssetHistory
A Simple Unity Editor Extension that records asset selection history
UnityAssetHistory
A Simple Unity Editor Extension that records asset selection history
Record asset selection history
The Unity Editor does not have a feature to return to previously selected assets.
This frequently leads to the question, Which asset was that one I just used?
Using this extension, the history of selected assets is recorded,
previousに選択したアセットにすぐに戻れるようになります。
インストール
INSTALL
1. Copy the source code below and place it in the Editor folder as a file named UnityAssetHistory.cs.
2. Open the window from Menu > Tools > Unity Asset History in the Unity Editor.
2. Open the window from Menu > Tools > Unity Asset History in the Unity Editor.
使い方
HOW TO USE

2. The selected asset will be automatically recorded.

3. Selected assets are automatically recorded in sequence. The last selected asset appears at the top.

4. Click the asset you want to return to, and you'll be back in no time. No more getting lost in the previous asset's location!

Source code
SOURCE CODE
UnityAssetHistory Source code
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>
/// UnityAssetHistory Ver 1.0.0
/// Copyright (c) 2025 MMGames
/// Released under the MIT License.
/// https://9cguide.appspot.com/unity_unity_asset_history.html
/// </summary>
public class UnityAssetHistory : EditorWindow
{
/// <summary>
/// 選択したアセットの履歴(variable名の変更にCaution)
/// </summary>
[SerializeField]
private List<Object> selectedAssetHistoryList = new();
/// <summary>
/// 現在のスクロール位置
/// </summary>
private Vector2 scrollPosition;
/// <summary>
/// アセットのみを対象とする(フォルダやシーン内オブジェクトは無視する)
/// </summary>
private bool IsAssetOlly = false;
/// <summary>
/// UnityEditorのメニューに登録
/// </summary>
[MenuItem("Tools/UnityAssetHistory")]
private static void RegisterMenu()
{
GetWindow<UnityAssetHistory>();
}
/// <summary>
/// 有効化
/// </summary>
private void OnEnable()
{
// アセット選択イベント
Selection.selectionChanged += OnSelectionChanged;
}
/// <summary>
/// Again描画
/// </summary>
private void OnGUI()
{
// SerializedObjectに変換する
var serializedObject = new SerializedObject(this);
serializedObject.Update();
// 選択したアセットの履歴を表示
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
EditorGUILayout.PropertyField(serializedObject.FindProperty("selectedAssetHistoryList"), true);
EditorGUILayout.EndScrollView();
EditorGUILayout.Space();
// クリーンbutton
if (GUILayout.Button("Clean"))
{
OnClickCleanButton();
}
}
/// <summary>
/// アセットが選択された
/// </summary>
private void OnSelectionChanged()
{
bool isRepaint = false;
// 選択されたオブジェクトを取得
var selectedObjectList = Selection.objects;
foreach (Object obj in selectedObjectList)
{
// アセットでなければ無視
if (IsAssetOlly)
{
if (IsAsset(obj) == false) return;
}
// すでに履歴に存在しているか?
var selectedAssetHistoryIndex = selectedAssetHistoryList.IndexOf(obj);
if (selectedAssetHistoryIndex >= 0)
{
// 存在しているなら削除(先頭に追加されるので一番上に移動する)
selectedAssetHistoryList.Remove(obj);
}
// Again描画フラグON
isRepaint = true;
// 先頭に追加
selectedAssetHistoryList.Insert(0, obj);
}
// アクセスできなくなったアセットがあれば消しておく
if (GCAll()) isRepaint = true;
// Again描画
if (isRepaint) Repaint();
}
/// <summary>
/// クリーンbuttonがクリックしされた
/// </summary>
private void OnClickCleanButton()
{
// 履歴がないなら何もしない
if (selectedAssetHistoryList.Count == 0) return;
// クリアしてAgain描画
selectedAssetHistoryList = new();
Repaint();
}
/// <summary>
/// アクセスできなくなったすべてのアセットを履歴から削除
/// </summary>
/// <returns></returns>
private bool GCAll()
{
// 1つもなければAgain描画不要
if (GCSingle() == false) return false;
// アクセスできなくなったアセットがある限り削除を繰り返す
while (GCSingle())
{
}
return true;
}
/// <summary>
/// アクセスできなくなったアセットを1つだけ履歴から削除
/// </summary>
/// <returns></returns>
private bool GCSingle()
{
// アクセスできなくなったアセットを探す
for (int i = 0; i < selectedAssetHistoryList.Count; i++)
{
if (selectedAssetHistoryList[i] == null)
{
// 見つかったら削除して戻る
selectedAssetHistoryList.RemoveAt(i);
return true;
}
}
// 1つもなかった
return false;
}
/// <summary>
/// 指定されたオブジェクトはアセットなのか?
/// </summary>
/// <param name="inObject"></param>
/// <returns></returns>
private bool IsAsset(Object inObject)
{
string assetPath = AssetDatabase.GetAssetPath(inObject);
return (assetPath.Length > 0);
}
/// <summary>
/// 解放
/// </summary>
private void OnDestroy()
{
Selection.selectionChanged -= OnSelectionChanged;
}
}
#endif
ライセンス
LICENSE
MIT License
Copyright 2025 MMGames
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Copyright 2025 MMGames
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.




