Commit 1
This commit is contained in:
175
Assets/Editor/AutoSaveTool.cs
Normal file
175
Assets/Editor/AutoSaveTool.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
// ===============================================================================
|
||||
// AutoSaveTool - Persistent & Robust Auto-Saving for Unity Editor
|
||||
//
|
||||
// Creator: Scove
|
||||
// Last Updated: 2024-05-08
|
||||
// Version: 2.0
|
||||
//
|
||||
// Purpose:
|
||||
// This tool provides a persistent, background auto-saving mechanism for the Unity Editor.
|
||||
// It runs automatically when Unity starts and saves all open scenes and modified assets
|
||||
// at a user-defined interval, even when the settings window is closed.
|
||||
//
|
||||
// Key Features:
|
||||
// 1. Runs persistently in the background via [InitializeOnLoad].
|
||||
// 2. Saves configuration (interval, status) using EditorPrefs, persisting across Unity sessions.
|
||||
// 3. Uses System.DateTime for accurate time tracking, unaffected by Play Mode reloads.
|
||||
// 4. Pauses counting down during Play Mode or compilation to prevent accidental saving.
|
||||
//
|
||||
// How to Use:
|
||||
// 1. Place this script in an 'Editor' folder in your project.
|
||||
// 2. Open the settings window via: Menu -> Tools -> Auto Save Settings.
|
||||
// 3. Enable "Bật Auto Save" (Enable Auto Save).
|
||||
// 4. Set the desired "Thời gian (phút)" (Interval in minutes).
|
||||
// 5. The tool will now save automatically in the background according to the schedule.
|
||||
// ===============================================================================
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
[InitializeOnLoad] // Critical: Ensures the script runs in the background upon Unity startup
|
||||
public class AutoSaveTool : EditorWindow
|
||||
{
|
||||
// Static Configuration Variables (Persisted via EditorPrefs)
|
||||
private static bool isAutoSaveEnabled;
|
||||
private static float saveIntervalMinutes;
|
||||
private static bool showDebugLog;
|
||||
|
||||
// Time Tracking Variable
|
||||
private static DateTime nextSaveTime;
|
||||
|
||||
// Static Constructor: Runs when Unity starts or recompiles
|
||||
static AutoSaveTool()
|
||||
{
|
||||
// 1. Load settings from EditorPrefs (persistent storage)
|
||||
isAutoSaveEnabled = EditorPrefs.GetBool("AutoSave_Enabled", false);
|
||||
saveIntervalMinutes = EditorPrefs.GetFloat("AutoSave_Interval", 5f);
|
||||
showDebugLog = EditorPrefs.GetBool("AutoSave_Log", true);
|
||||
|
||||
// 2. Initialize the timer
|
||||
ResetTimer();
|
||||
|
||||
// 3. Register the background update loop
|
||||
EditorApplication.update += OnEditorUpdate;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Auto Save Settings")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<AutoSaveTool>("Auto Save");
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Label("Auto Save Configuration (Runs in Background)", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// Begin tracking changes on the GUI
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
isAutoSaveEnabled = EditorGUILayout.Toggle("Enable Auto Save", isAutoSaveEnabled);
|
||||
saveIntervalMinutes = EditorGUILayout.FloatField("Interval (Minutes)", saveIntervalMinutes);
|
||||
showDebugLog = EditorGUILayout.Toggle("Show Debug Log", showDebugLog);
|
||||
|
||||
// If any setting changed, save it immediately to EditorPrefs
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (saveIntervalMinutes < 0.5f) saveIntervalMinutes = 0.5f; // Minimum 30 seconds
|
||||
|
||||
EditorPrefs.SetBool("AutoSave_Enabled", isAutoSaveEnabled);
|
||||
EditorPrefs.SetFloat("AutoSave_Interval", saveIntervalMinutes);
|
||||
EditorPrefs.SetBool("AutoSave_Log", showDebugLog);
|
||||
|
||||
ResetTimer(); // Reset timer based on new settings
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (isAutoSaveEnabled)
|
||||
{
|
||||
TimeSpan timeRemaining = nextSaveTime - DateTime.Now;
|
||||
if (timeRemaining.TotalSeconds < 0) timeRemaining = TimeSpan.Zero;
|
||||
|
||||
// Display warning if Play Mode or Compiling
|
||||
if (EditorApplication.isPlaying || EditorApplication.isCompiling)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Currently in Play Mode or Compiling. Saving is temporarily paused to prevent errors.", MessageType.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
string timeStr = string.Format("{0:00}:{1:00}", timeRemaining.Minutes, timeRemaining.Seconds);
|
||||
EditorGUILayout.HelpBox($"System is running in background.\nAuto-saving in: {timeStr}", MessageType.Info);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Save Now", GUILayout.Height(30)))
|
||||
{
|
||||
SaveNow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("Auto Save System is currently DISABLED.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// This function runs continuously in the background
|
||||
private static void OnEditorUpdate()
|
||||
{
|
||||
if (!isAutoSaveEnabled) return;
|
||||
|
||||
// If playing or compiling -> PAUSE the countdown (do not reset)
|
||||
if (EditorApplication.isPlaying || EditorApplication.isCompiling)
|
||||
{
|
||||
// Add delta time to nextSaveTime to compensate for time elapsed while paused
|
||||
nextSaveTime = nextSaveTime.AddSeconds(Time.unscaledDeltaTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's time to save
|
||||
if (DateTime.Now >= nextSaveTime)
|
||||
{
|
||||
SaveNow();
|
||||
}
|
||||
|
||||
// Repaint the GUI if the window is open to keep the countdown smooth
|
||||
if (HasOpenInstances<AutoSaveTool>())
|
||||
{
|
||||
GetWindow<AutoSaveTool>().Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetTimer()
|
||||
{
|
||||
nextSaveTime = DateTime.Now.AddMinutes(saveIntervalMinutes);
|
||||
}
|
||||
|
||||
private static void SaveNow()
|
||||
{
|
||||
var currentScene = EditorSceneManager.GetActiveScene();
|
||||
|
||||
bool isSaved = false;
|
||||
|
||||
// 1. Save Current Scene if it is dirty AND has a path (not Untitled)
|
||||
if (currentScene.isDirty && !string.IsNullOrEmpty(currentScene.path))
|
||||
{
|
||||
EditorSceneManager.SaveOpenScenes();
|
||||
isSaved = true;
|
||||
}
|
||||
|
||||
// 2. Always save Assets (Prefabs, ScriptableObjects, etc.)
|
||||
AssetDatabase.SaveAssets();
|
||||
isSaved = true;
|
||||
|
||||
if (isSaved && showDebugLog)
|
||||
{
|
||||
Debug.Log($"<color=#00FF00><b>[AutoSave]</b></color> Project saved automatically at {DateTime.Now.ToString("HH:mm:ss")}");
|
||||
}
|
||||
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user