UnityAssetHistory

UnityAssetHistory

アセットの選択履歴を記録するシンプルなエディタ拡張


ソースコードをコピペする

UnityAssetHistory

アセットの選択履歴を記録するシンプルなエディタ拡張

ソースコードをコピペする


アセット選択履歴を記録


Unity Editor には、以前に選択したアセットに戻る機能がありません。
そのため「さっきのアセットはどれだっけ?」が頻繁に発生します。

本拡張機能を使えば、選択したアセットの履歴が記録され、
以前に選択したアセットにすぐに戻れるようになります。


インストール
INSTALL
1、下記のソースコードをコピーして、UnityAssetHistory.cs というファイル名で、Editorフォルダに配置する。
2、Unity Editor で「メニュー > Tools > UnityAssetHistory」からウィンドウを開く。
使い方
HOW TO USE
Project View でアセットを選択します。




2、選択したアセットが自動的に記録されます。




3、選択したアセットは自動で順番に記録されます。最後に選択したアセットが一番上に表示されます。




4、戻りたいアセットをクリックすればすぐに戻ることができます。さっきのアセットの場所で迷うことはもうありません!



ソースコード
SOURCE CODE


UnityAssetHistory ソースコード
#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>
    /// 選択したアセットの履歴(変数名の変更に注意)
    /// </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>
    /// 再描画
    /// </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();

        // クリーンボタン

        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);
            }

            // 再描画フラグON

            isRepaint = true;

            // 先頭に追加

            selectedAssetHistoryList.Insert(0, obj);
        }

        // アクセスできなくなったアセットがあれば消しておく

        if (GCAll()) isRepaint = true;

        // 再描画

        if (isRepaint) Repaint();
    }

    /// <summary>
    /// クリーンボタンがクリックしされた
    /// </summary>
    private void OnClickCleanButton()
    {
        // 履歴がないなら何もしない

        if (selectedAssetHistoryList.Count == 0) return;

        // クリアして再描画

        selectedAssetHistoryList = new();
        Repaint();
    }

    /// <summary>
    /// アクセスできなくなったすべてのアセットを履歴から削除
    /// </summary>
    /// <returns></returns>
    private bool GCAll()
    {
        // 1つもなければ再描画不要

        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 で提供いたします。商用、非商用を問わず、自由に使用、改変、再配布が可能です。
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.

コメントシステムを読込中・・・