顺势而为47 发表于 2021-2-25 09:33

游戏开发踩坑记录(二)Unity Inspector Preview 面版卡顿问题

1.起因

项目组最近升级了Unity引擎,从基于2018.3.6f1修改的自编版本升级到2018.4.11f1官方版本。在升级后,很多美术同学找到我反应说他们在使用资源的Inspector面板时非常卡,严重影响他们的制作效率。
初步观察了下卡顿现象,发现只要Inspector面板中显示的Preview窗口,卡顿就出现了。先让美术同学把Preview窗口关掉,然后开始想办法定位问题。
2.问题定位

通过Deep Profiler Editor,发现了卡顿的元凶:AssetBundleNameGUI类在OnGUI时会调用GetAllAssetBundleNames。由于项目中AssetBundleName量级比较大,所以卡顿明显。
3.修改方案

查看Unity开源出来的C#代码 ( https://github.com/Unity-Technologies/UnityCsReference),可以观察到Inspector相关代码的调用顺序:
(1)每个Inpspector窗口对应的是InspectorWindow类,该类中有一个私有成员m_AssetBundleNameGUI。
(2)在Inpspector的OnGUI函数中,如果显示Preview并且资源存在AssetBunldeName。会调用m_AssetBundleNameGUI的OnAssetBundleNameGUI。
(3)在OnAssetBundleNameGUI函数中,如果m_ShowAssetBundleNameTextField字段为false,会调用AssetBundlePopup,从而调用AssetDatabase.GetAllAssetBundleVariants
在不改引擎的情况下,要如何避免调用GetAllAssetBundleVariants呢?
目前我只想到用反射的方式:获取Editor中所有Inspector,将他们的m_AssetBundleNameGUI中的m_ShowAssetBundleNameTextField,强制改为true。具体代码如下:
// 初始化
{
    Assembly assembly = Assembly.GetAssembly(typeof(Editor));
    Type InspectorWindow = assembly.GetType("UnityEditor.InspectorWindow");
    Type AssetBundleNameGUI = assembly.GetType("UnityEditor.AssetBundleNameGUI");
    m_AllInspectors = InspectorWindow.GetField("m_AllInspectors",BindingFlags.Static | BindingFlags.NonPublic);
    m_AssetBundleNameGUI = InspectorWindow.GetField("m_AssetBundleNameGUI",BindingFlags.Instance | BindingFlags.NonPublic);
    m_ShowAssetBundleNameTextField =AssetBundleNameGUI.GetField("m_ShowAssetBundleNameTextField",BindingFlags.Instance | BindingFlags.NonPublic);
}


// 每帧调用
{
    object value = m_AllInspectors.GetValue(null);
    var enumerator = ((IEnumerable)value).GetEnumerator();
    while (enumerator.MoveNext())
    {
      var ins = enumerator.Current;
      object abname = m_AssetBundleNameGUI/span><span class="p">.GetValue(ins);
      m_ShowAssetBundleNameTextField.SetValue(abname, true);
    }
}
这样的修改并不是很完美,比较取巧。但暂时解决了美术同学制作时的卡顿问题。 大家如果有更好的方案,欢迎指导。
页: [1]
查看完整版本: 游戏开发踩坑记录(二)Unity Inspector Preview 面版卡顿问题