开发中当Unity项目比较大的时候,每次Unity窗口获取焦点时刷新需要3-5秒,非常麻烦!常见有几种方法来缓解这个问题:
- 关闭unity自动刷新Edit->Preferences->General->Auto Refresh,改为自己手动Ctrl+R刷新;
缺点:每次都需要手动刷新比较麻烦
- 修改unity的ScriptChangesWhilePlaying选项Editor->Preferences->General->Script Changes While Playing
Recompile And Continue Playing 编译并继续播放
Recompile After Finished Playing 停止播放后再编译
Stop Playing And Recompile 停止播放进行编译
- 开发工具在Editor模式自动检查资源变更自动刷新,代码如下:
第一步:检查开发过程中需要及时刷新的资源,如:Scripts目录,prefab目录
第二步:获取最后改动时间是否与上一次检查的时间一致,不一致则启动刷新
第三步:将时间写入文件缓存,方便下一次对比
第四步:在窗口获取焦点以及Playing启动时启动检测
2024.3.8:新增SVN的Resivion版本对比刷新功能 ,如果Resivion比缓存中版本号大则启动刷新并保存当前Resivion号;
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
[InitializeOnLoad]
public class EditorNotification : AssetPostprocessor
{
private static bool isFocused;
private static bool isPlaymode;
static EditorNotification()
{
EditorApplication.update -= Update;
EditorApplication.update += Update;
EditorApplication.playmodeStateChanged -= PlaymodeStateChanged;
EditorApplication.playmodeStateChanged += PlaymodeStateChanged;
}
private static void Update()
{
if (isFocused == UnityEditorInternal.InternalEditorUtility.isApplicationActive)
{
return;
}
isFocused = UnityEditorInternal.InternalEditorUtility.isApplicationActive;
OnEditorFocus(isFocused);
}
private static void PlaymodeStateChanged()
{
if(EditorApplication.isPlayingOrWillChangePlaymode && !isPlaymode)
{
//Debug.LogError(EditorApplication.isPlaying.ToString() + " - " + EditorApplication.isPlayingOrWillChangePlaymode.ToString());
isPlaymode = true;
Refresh();
}
else if(!EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying)
{
isPlaymode = false;
}
}
/// <summary>
/// Unity窗口聚焦状态改变回调
/// </summary>
/// <param name="focus"></param>
private static void OnEditorFocus(bool focus)
{
if (focus)
{
//Debug.LogErrorFormat("编辑器激活状态:{0}", focus);
if(!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode)
{
Refresh();
}
}
}
private void OnPreprocessAsset()
{
//Debug.LogError("Asset下文件改变时回调");
}
//[MenuItem("File/RefreshManual")]
static void Refresh()
{
bool needRefresh = false;
MD5File md5 = new MD5File();
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Reset();
sw.Start();
string path = Path.Combine($"{Application.dataPath}/../Library", "md5Refresh.dat");
if(File.Exists(path))
{
FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
BinaryFormatter bin = new BinaryFormatter();
md5 = (MD5File)bin.Deserialize(fs);
fs.Close();
}
string scriptPath = Path.Combine($"{Application.dataPath}", "Scripts");
DirectoryInfo dinfo = new DirectoryInfo(scriptPath);
FileInfo[] fileInfos = dinfo.GetFiles("*.cs", SearchOption.AllDirectories);
foreach(FileInfo file in fileInfos)
{
string timestr = file.LastWriteTime.ToLongTimeString();
string value = string.Empty;
if(md5.m_DicMD5.TryGetValue(file.FullName, out value))
{
System.DateTime dt = System.DateTime.Parse(value);
System.DateTime dt2 = System.DateTime.Parse(timestr);
if(!System.DateTime.Equals(dt, dt2))
{
needRefresh = true;
md5.m_DicMD5[file.FullName] = timestr;
Debug.LogError(file.FullName + " - " + value + " -- " + timestr);
}
}
else
{
needRefresh = true;
md5.m_DicMD5.Add(file.FullName, timestr);
Debug.LogError(file.FullName + " -------- " + timestr);
}
}
//刷新SVN版本号并对比
bool bNeedRefreshSVN = CheckSVNRevision(md5);
{
FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(fs, md5);
fs.Close();
}
sw.Stop();
string str;
if (needRefresh)
{
str = "C#变更检查结束,需要刷新!";
string t = (sw.Elapsed.TotalMilliseconds / 1000).ToString("N2");
Debug.LogError($"{str}FileCount:{fileInfos.Length} Time:{t}秒");
AssetDatabase.Refresh();
EditorUtility.RequestScriptReload();
}
else if(bNeedRefreshSVN)
{
str = "SVN有更新,需要刷新!";
Debug.LogError(str);
AssetDatabase.Refresh();
EditorUtility.RequestScriptReload();
}
}
static bool CheckSVNRevision(MD5File md5)
{
if (md5.m_DicSVNRevision == null)
md5.m_DicSVNRevision = new System.Collections.Generic.Dictionary<string, uint>();
bool bret = false;
string path = Application.dataPath;
uint revisionID = 0;
revisionID = GetSVNRevision(path);
uint cacheID = 0;
if (md5.m_DicSVNRevision.TryGetValue(path, out cacheID))
cacheID = md5.m_DicSVNRevision[path];
if (revisionID > 0 && revisionID > cacheID)
{
md5.m_DicSVNRevision[path] = revisionID;
bret = true;
}
//DirectoryInfo dirInfo = new DirectoryInfo(path);
//DirectoryInfo[] infos = dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly);
string[] infos = new string[4];
infos[0] = Path.Combine(path, "Art");
infos[1] = Path.Combine(path, "Document");
infos[2] = Path.Combine(path, "lua");
infos[3] = Path.Combine(path, "UI");
foreach (var info in infos)
{
cacheID = 0;
path = info;
revisionID = GetSVNRevision(path);
if (md5.m_DicSVNRevision.TryGetValue(path, out cacheID))
cacheID = md5.m_DicSVNRevision[path];
if (revisionID > 0 && revisionID > cacheID)
{
md5.m_DicSVNRevision[path] = revisionID;
bret = true;
}
}
return bret;
}
/// <summary>
/// 获取svn版本revision号
/// </summary>
/// <param name="path">svn路径</param>
/// <returns>uint revision号</returns>
static uint GetSVNRevision(string path = "")
{
var startInfo = new System.Diagnostics.ProcessStartInfo("svn", "info " + path)
{
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using (var process = System.Diagnostics.Process.Start(startInfo))
{
using (var reader = process.StandardOutput)
{
// 读取命令的输出直到结束
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if(line.StartsWith("Last Changed Rev"))
{
int index = line.IndexOf(":");
string strID = line.Substring(index + 1);
uint revisionID = 0;
if(uint.TryParse(strID, out revisionID))
{
//Debug.LogError(revisionID.ToString() + " - " + path);
return revisionID;
}
}
}
}
}
return 0;
}
}
#endif
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class MD5File
{
public Dictionary<string, string> m_DicMD5 = new Dictionary<string, string>();
public Dictionary<string, uint> m_DicSVNRevision = new Dictionary<string, uint>();
}
这种方法只需要检查少部分资源自动刷新,基本没有卡顿,体验相对比较好!