Unity项目较大刷新及编译卡顿解决方法

开发中当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>();
}

 这种方法只需要检查少部分资源自动刷新,基本没有卡顿,体验相对比较好!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值