PR

【Unityプラグイン】アセットを一括で名前変更(リネーム)するツール

Unity

今回はUnityに登録しているデータを一括で名前を変更したいことがあったのでファイル名を一括変更できるプラグインを作成してみました。

同じように数十個、数百個のファイルのリネームに苦労している人の助けになれば幸いです。

プラグインについて

本プラグインを使うと面倒なアセット名の変更を一括で行うことができます。
私もアセットを大量の名前を変更する必要があったので実験的に作成してみました。

データが大量にある場合に便利だと思われます

 

更新履歴

  • 2022/07/11
    公開
  • 2022/07/28
    「フォルダ開く」を位置を変更
    検索結果を表示、検索結果から置き換え処理に変更
  • 2022/08/13
    フォルダを指定する参照ボタン追加
    対象ファイルを限定するためのフィルタ追加(置き換える文字列とは別に用意)
    検索結果をクリップボードに保存するボタン追加
    名称変更後、参照先が更新されない不具合修正
    検索結果から再保存を行うボタンを追加
  • 2024/01/04
    「対象フォルダのみ」が機能していなかった不具合を修正

ダウンロード

ダウンロードはこちら
[Unity]ファイル名一括変換プラグイン

インストール方法

unitypackageのインストール方法はこちらです。

 

ソースコード

TedLab_ReplaceFileNameEditor.cs

using System;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Linq;

namespace TedLab
{
    public class ReplaceFileNameWindow : EditorWindow
    {
        [MenuItem("TedLab/ファイル名を一括置き換え")]
        static void OpenWindow()
        {
            GetWindow(true, "[TedLab]ファイル名を一括置き換え");
        }

        static readonly string KeyPrefix = "TedLab_ReplaceFileName_";
        static readonly string PathKey = KeyPrefix + "Path";
        static readonly string FilterTextKey = KeyPrefix + "FilterText";
        static readonly string MatchTextKey = KeyPrefix + "MatchText";
        static readonly string ReplaceTextKey = KeyPrefix + "ReplaceText";
        static readonly string IsCurrentFolderKey = KeyPrefix + "IsCurrentFolder";

        private string _targetPath = "";
        private string _filterText = "";
        private string _matchText = "";
        private string _replaceText = "";
        private bool _isOnlyCurrentFolder = true;

        private Vector2 _scrollPosition = Vector2.zero;
        private List _foundPath = new List();

        private void OnEnable()
        {
            _targetPath = EditorPrefs.GetString( PathKey, "");
            _filterText = EditorPrefs.GetString( FilterTextKey, "");
            _matchText = EditorPrefs.GetString( MatchTextKey, "");
            _replaceText = EditorPrefs.GetString( ReplaceTextKey, "");
            _isOnlyCurrentFolder = EditorPrefs.GetBool(IsCurrentFolderKey, true);
        }

        private void OnDisable()
        {
            EditorPrefs.SetString( PathKey, _targetPath );
            EditorPrefs.SetString( FilterTextKey, _filterText );
            EditorPrefs.SetString( MatchTextKey, _matchText );
            EditorPrefs.SetString( ReplaceTextKey, _replaceText );
            EditorPrefs.SetBool( IsCurrentFolderKey, _isOnlyCurrentFolder );
        }

        void OnGUI()
        {
            {
                GUILayout.Label("設定");
                _isOnlyCurrentFolder = GUILayout.Toggle(_isOnlyCurrentFolder, "対象フォルダのみ");
                EditorGUILayout.Separator();
            }
            
            {
                GUILayout.Label("対象フォルダ");
                {
                    var newTargetPath = GUILayout.TextField(_targetPath);
                    if (newTargetPath != _targetPath)
                    {
                        if (Path.HasExtension(newTargetPath)) {
                            var fileName = Path.GetFileName(newTargetPath);
                            _targetPath = newTargetPath.Replace( Path.DirectorySeparatorChar + fileName, "");
                        } else {
                            _targetPath = newTargetPath;
                        }
                    }
                }

                if (GUILayout.Button("参照"))
                {
                    var path = string.IsNullOrEmpty(_targetPath) ? "Assets" : _targetPath;
                    var resultPath = EditorUtility.OpenFolderPanel("対象フォルダを選択", path, "");
                    if (resultPath.Contains(Application.dataPath))
                    {
                        _targetPath = resultPath.Replace(Application.dataPath, "Assets");
                    }
                }
                EditorGUILayout.Separator();
            }

            {
                GUILayout.Label("検索フィルター(スペースで複数可能)");
                _filterText = GUILayout.TextField(_filterText);
                
                GUILayout.Label("置き換え元の文字列");
                _matchText = GUILayout.TextField(_matchText);

                GUILayout.Label("置き換え後の文字列");
                _replaceText = GUILayout.TextField(_replaceText);

                if (GUILayout.Button("検索"))
                {
                    FindAssets();
                }
                EditorGUILayout.Separator();
            }

            {
                EditorGUILayout.PrefixLabel("検索結果");
                if (GUILayout.Button("検索結果で一括置き換え"))
                {
                    ReplaceText();
                    FindAssets();
                }

                if (GUILayout.Button("検索結果でアセット再保存"))
                {
                    _foundPath.ForEach(SetDirtyAsset);
                    AssetDatabase.SaveAssets();
                }
                EditorGUILayout.Separator();
            }

            using (new EditorGUILayout.HorizontalScope())
            {
                GUILayout.Label("対象パス一覧");
                if (GUILayout.Button("クリップボード"))
                {
                    var resultText = "";
                    foreach(var path in _foundPath)
                    {
                        if(!string.IsNullOrEmpty(resultText)){
                            resultText += Environment.NewLine;
                        }
                        resultText += path;
                    }
                    GUIUtility.systemCopyBuffer = resultText;
                }
            }
            
            {
                _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
                foreach(var path in _foundPath){
                    EditorGUILayout.LabelField(path);
                }
                EditorGUILayout.EndScrollView();
            }
        }

        private void FindAssets()
        {
            var filterText = $"{_filterText} {_matchText}";
            var guids = AssetDatabase.FindAssets(filterText, new[] {_targetPath});
            if(guids.Length <= 0){
                _foundPath.Clear();
                return;
            }
            _foundPath = new List(guids.Length);
            foreach(var guid in guids)
            {
                var path = AssetDatabase.GUIDToAssetPath(guid);
                var extension = Path.GetExtension(path);
                if (string.IsNullOrEmpty(extension)){
                    continue;
                }
                var fileName = Path.GetFileName(path);
                if (string.IsNullOrEmpty(fileName) || !fileName.Contains(_matchText)) {
                    continue;
                }
                
                if (_isOnlyCurrentFolder)
                {
                    var directoryPath = path.Replace(Path.AltDirectorySeparatorChar + fileName, "");
                    if (directoryPath != _targetPath){
                        continue;
                    }
                }
                _foundPath.Add(path);
            }
        }

        void ReplaceText()
        {
            foreach(var path in _foundPath)
            {
                var fileName = Path.GetFileName(path);
                var newFileName = fileName.Replace(_matchText, _replaceText);
                AssetDatabase.RenameAsset(path, newFileName);
                
                var newPath =path.Replace(fileName, "") + newFileName;
                SetDirtyAsset(newPath);
            }
            AssetDatabase.SaveAssets();
        }

        private static void SetDirtyAsset(string path)
        {
            var type = AssetDatabase.GetMainAssetTypeAtPath(path);
            var asset = AssetDatabase.LoadAssetAtPath(path, type);
            EditorUtility.SetDirty(asset);
        }
    }

} // namespace TedLab

 

利用の流れ

おおまかな使い方としては

  1. 本プラグイン(スクリプト)をプロジェクトに追加する
  2. メニューにある「TedLab→ファイル名を一括置き換え」を選択
  3. 専用ウィンドウが開かれる
  4. 対象となるフォルダへのパスを設定(参照ボタンで指定可能)
  5. フィルターなどを設定(対象ファイルを限定する機能)
  6. 置き換え元、置き換え後の文字列を設定
  7. 検索ボタンを押して、対象となるファイルを確認
  8. 置き換えボタンを押す

となります。

基本的にはテキストエディタなどで対象を検索して
置換するのと同じような感じです

 

使用方法

まずはプロジェクトにプラグイン(スクリプト)を追加しましょう。
上記からダウンロードしてunitypackageをインストールしてください。

スクリプトをプロジェクトにドラッグ&ドロップするだけでもOKです

追加できたら「メニュー→TedLab→ファイル名を一括置き換え」を選択します。
すると専用ウィンドウが表示されるので順次設定していきます。

設定方法

具体的な設定項目は下記となります。

設定項目解説

  • 設定→対象フォルダのみ
    検索する場所を指定フォルダのみ
  • 対象フォルダ
    対象となるファイルがあるフォルダを指定(参照ボタンでも可)
  • 検索フィルター
    特定ファイルに限定したい場合に利用(t:などで型名指定など)
  • 置き換え元の文字列
    指定フォルダ内で対象となるアセットをこの文字列から探す
  • 置き換え後の文字列
    検索文字列をこの文字列で置き換えるための名前
  • 検索ボタン
    上記設定を元に置き換え対象をパスを一覧で表示
  • 検索結果で一括置き換え
    検索でヒットしたパスに対し、リネーム
  • 検索結果でアセット再保存
    参照先の名前が変わっていないなどの不具合があったの場合のボタン
上記を設定して「検索ボタン」→「検索結果で一括置き換え」の順に押すとファイル名が変更されます。

フィルターは「t:スクリプト名」で
型名指定もできるので是非ご活用ください!

 

実際に置き換えてみる

そして私の場合は「LocalizeTextTable_」が頭についたアセットがたくさんあって
その文字列を消したかったので「置き換える文字列」に空文字(何も入力しない)を指定しました。
そして実行すると

ドキドキ…

下記のように変換されました。

何十個もあったファイルの名前が変わりました!

こりゃ便利。

 

活動内容のPR

下記が本サイトでの活動内容となります。

他の開発動画を見る

 

最後に

いかがでしたでしょうか。

これまでは大した量でもないので手作業でリネームなどしていましたが
今後は大量のデータでも問題なく作業できそうです。

シンプルなのにとても便利。
今後も重宝しそうな予感MAXです!

では本記事はここで終わりたいと思います。
このプラグインが無用な作業を減らせる助けとなれば幸いです。
この度はここまでお読みいいただきありがとうございました。

 

コメント

  1. z より:

    大変助かりました、ありがとうございます!

スポンサーリンク
タイトルとURLをコピーしました