Files
Test-Multiplayer/Library/PackageCache/com.unity.dedicated-server@5a2666836321/Common/Editor/SyncedSingleton.cs
pelpanagiotis 329b7d3183 First Commit
2025-12-21 18:31:02 +02:00

66 lines
2.3 KiB
C#

using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Assertions;
namespace Unity.Multiplayer.Editor
{
// A ScriptableSingleton that syncs its data to and from a file on disk.
// This is specially necessary for virtual projects where the main Editor serializes the data to a file
// and the other instances of the Editor needs to reload the data from that file when changed.
internal class SyncedSingleton<T> : ScriptableSingleton<T> where T : ScriptableObject
{
private static bool s_NeedsRegeneration;
// If the file is updated and the editor is not in focus and entered play mode
// before focus is regained (e.g. multiplayer play mode), then the regeneration
// method --called through delayCall-- could be executed after play mode.
// To avoid this, we reload it on entering play mode state change. It's redundant
// but safer.
private static void OnPlayModeStateChanged(PlayModeStateChange state)
{
ReloadIfNeeded();
}
static SyncedSingleton()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private static void OnFileChanged(object source, FileSystemEventArgs e)
{
s_NeedsRegeneration = true;
((IDisposable)source).Dispose();
EditorApplication.delayCall += ReloadIfNeeded;
}
private static void ReloadIfNeeded()
{
if (s_NeedsRegeneration)
{
// By deleting the instance the Editor will reload the data from the file.
DestroyImmediate(instance);
s_NeedsRegeneration = false;
}
}
private FileSystemWatcher m_FileWatcher;
protected void OnEnable()
{
Assert.IsNull(m_FileWatcher);
var directory = Path.GetDirectoryName(ScriptableSingleton<T>.GetFilePath());
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
m_FileWatcher = new FileSystemWatcher();
m_FileWatcher.Path = directory;
m_FileWatcher.Changed += OnFileChanged;
m_FileWatcher.Created += OnFileChanged;
m_FileWatcher.EnableRaisingEvents = true;
}
}
}