【Unity】操作不要・完全自動でファイルのバックアップを保存するアセットを公開してみる

Unity のバックアップを全自動で保存する
Unity のアセットを作成しました。
皆さんの役に立てればと思い
公開してみたいと思います。

[本体はこちら(Unity Asset Store)](https://assetstore.unity.com/packages/tools/utilities/sephiroth-auto-back-up-monitoring-290378)
[本体はこちら(BOOTH)](https://giftedstyle.booth.pm/items/5901908)
[本体はこちら(Google Drive)](https://drive.google.com/file/d/1hgtydaiAD90d6XnKf_qctbw0tPWVAbem/view?usp=sharing)

***
このアセットは、ファイルが更新されるたびに自動でバックアップを保存します。
インポートするだけで機能し、追加の操作は一切不要です。

＜主な機能＞
・Unity プロジェクトの「Assets」フォルダと同じ階層に「Assets_BackUP」フォルダが自動で作成されます。
・「Assets」フォルダ内のファイルが更新されるたびに、そのファイルのバックアップが「Assets_BackUP」に保存されます。
・バックアップファイル名には更新日時が含まれており、過去の状態に戻す際の目安になります。
・4 作業日以上前のバックアップファイルを一部自動で削除します。（その日最後の状態のみを保持）（v1.0.0 のみ）
・「Assets_BackUP」フォルダを削除すると、現在の状態のみを含む新しいフォルダが自動で再生成されます。

※「Assets_BackUP」フォルダのサイズが大きくなりすぎた場合は、手動で削除することをおすすめします。

＜安全性について＞
このアセットは、「Assets」フォルダ内のファイルを一切書き換えません。
操作対象は「Assets_BackUP」フォルダのみであり、プロジェクトのデータに影響を与えることはありません。
安心してご利用いただけます。

＜Ctrl + S 連打対策も万全＞
Ctrl + S を連打してしまった場合にも対応済みです。
バックアップを保存した直後から 5 秒間は重複保存されない設計になっています。
たとえば、6 秒間に Ctrl + S を30回押したとしても、実際に作成されるバックアップは最大で 2 回に抑えられます。

![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/a98fb255-aa68-0d96-3846-95e4a7d98651.png)
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/21bbcc71-c6f2-d6f9-90cf-988d5db645fc.png)
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/81497dc5-309d-046d-206d-b9e5b86319c6.png)

***

このアセットのコード

ver0.0.0 は以下のコードで動作しています。
ver1.0.0 では 4 作業日以上前のバックアップファイルを
ある程度削除する機能が盛り込まれていますが
コードが長いため ver0.0.0 のコードを載せます。

SephirothAutoBackUPMonitoring.cs を新規作成して
コードを下記のコードに差し替えて
Editor フォルダに入れても
ver0.0.0 の状態で動作すると思います。

```Csharp:SephirothAutoBackUPMonitoring.cs
using System.Threading.Tasks;

namespace SephirothTools
{
    public class SephirothAutoBackUPMonitoring
    {
        private static readonly object Lock = new();
        private static bool isExec = false;
        private static string DateString;

        public const bool isCSharpFileOnly = false;

        [UnityEditor.InitializeOnLoadMethod]
        private static void Exec()
        {
            lock (Lock)
            {
                if (isExec)
                {
                    return;
                }
                isExec = true;
                Task.Run(() => TaskExec(System.DateTime.Now.ToString("yyyyMMdd-HHmmss")));
            }
        }

        private static void TaskExec(string date)
        {
            DateString = date;
            while (true)
            {
                try
                {
                    ExecOneTime();
                }
                catch
                {

                }
                System.Threading.Thread.Sleep(5000); // A thread for SephirothAutoBackUPMonitoring is generated and put into sleep, so the main thread is not stopped.
                if(date != DateString)
                {
                    break;
                }
            }
        }

        private static void ExecOneTime()
        {
            string targetPath = System.IO.Directory.GetCurrentDirectory() + "\\Assets_BackUP";
            if (!System.IO.Directory.Exists(targetPath))
            {
                System.IO.Directory.CreateDirectory(targetPath);
            }

            foreach (string onePath in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory() + "\\Assets", "*", System.IO.SearchOption.AllDirectories))
            {
                try
                {
                    if (isCSharpFileOnly && !onePath.EndsWith(".cs"))
                    {
                        continue;
                    }

                    string oneTargetDirectory = System.IO.Directory.GetCurrentDirectory() + "\\Assets_BackUP" + onePath.Substring((System.IO.Directory.GetCurrentDirectory() + "\\Assets").Length);
                    oneTargetDirectory = oneTargetDirectory.Substring(0, oneTargetDirectory.LastIndexOf("\\"));

                    string oneTargetFileName = System.IO.File.GetLastWriteTime(onePath).ToString("yyyyMMdd-HHmmss") + "_" + System.IO.Path.GetFileName(onePath);

                    string target = oneTargetDirectory + "\\" + oneTargetFileName;

                    if (!System.IO.File.Exists(target))
                    {
                        string[] pathMove = oneTargetDirectory.Split("\\");
                        string folderPath = pathMove[0];

                        for (int i = 1; i < pathMove.Length; i++)
                        {
                            folderPath = folderPath + "\\" + pathMove[i];
                            if (!System.IO.Directory.Exists(folderPath))
                            {
                                System.IO.Directory.CreateDirectory(folderPath);
                            }
                        }

                        System.IO.File.Copy(onePath, target);
                    }
                }
                catch
                {

                }
            }
        }
    }
}
```
***

以上 Unity のバックアップを
全自動で保存するアセットを公開しました。

Git による管理の場合
コミットを長期間忘れる傾向にある人は
是非こちらを併用する事を検討してみてはいかがでしょうか？
その場合は Assets_BackUP フォルダを Git の対象外にして下さい。

皆さんの開発の助けになれますように
閲覧ありがとうございました。