共计 5424 个字符,预计需要花费 14 分钟才能阅读完成。
1)Addressable 热更新资源类型的疑难
2)本地删除 FBX 的 DefaultMaterial 在 Unity 重启后生效
3)如何实现 MeshRenderer 的成果
4)UGUI 动静加载 Item 的 DrawCall 问题
5)Loading.CheckConsistency [Editor Only] 编辑器上的优化问题
这是第 250 篇 UWA 技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫 10 分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ 群 2:793972859(原群已满员)
Addressable
Q:Addressable 能够热更新 Text/Xml 等原始资源,不走 AssetBundle 吗?正在思考是否应用 Addressable 作为热更新计划,有一些资源不想走 AssetBundle,想间接读取,不晓得 Addressable 是否反对?
A:Addressable 目前没有间接反对 Raw 资源,根本都是走 AssetBundle 的。
一个思路就是把这些资源独自打 AssetBundle,以 AssetBundle 为载体,逻辑上还是当成独自的 Text,Binary 去读取;另外一个思路就是做扩大革新。
能够看到有 TextDataProvider 这个 Provider 类,外部用“File.ReadAllText(path);”获取资源,因而其实能够去实现一下 AddressableAssetGroupSchema 和 BuildScriptBase,做一个 RawAssetSchema 和 BuildScriptRawAsset 的扩大来打包。
感激黄程 @UWA 问答社区提供了答复
Editor
Q:用了 Addressables 零碎,打包 AssetBundle 有 Default Material 有冗余,在打包机上运行脚本把 FBX 的默认材质删除后变紫,然而从新关上工程后默认材质又回来了,导致冗余还在。(Unity 版本 2018.4.34)
删除材质的脚本:
using System;
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using Object = UnityEngine.Object;
class DisableMaterialImport : AssetPostprocessor {[MenuItem("Tools/Reimport All Model")]
public static void ReimportAllModel()
{var assetPaths = AssetDatabase.GetAllAssetPaths();
Array.Sort(assetPaths);
Debug.LogWarning(string.Format("Total assets count: {0}", assetPaths.Length));
int processedCount = 0;
foreach (string assetPath in assetPaths)
{string normalizedAssetPath = assetPath.ToLower();
if (!normalizedAssetPath.EndsWith(".fbx") &&
!normalizedAssetPath.EndsWith(".obj") &&
!normalizedAssetPath.EndsWith(".3ds"))
{continue;}
var modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
if (modelImporter == null || modelImporter.importMaterials)
{continue;}
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate);
Debug.Log(assetPath, AssetDatabase.LoadMainAssetAtPath(assetPath));
processedCount++;
}
Debug.LogWarning(string.Format("Total processed model count: {0}", processedCount));
AssetDatabase.SaveAssets();}
private static void FixedModelImport(ModelImporter modelImporter, GameObject model)
{//Debug.Log("FixedModelImport"+model);
var renderers = model.GetComponentsInChildren<Renderer>(true);
if (renderers == null)
{return;}
modelImporter.importMaterials = false;
modelImporter.importBlendShapes = false;
modelImporter.importAnimation = false;
modelImporter.isReadable = false;
modelImporter.optimizeMesh = true;
foreach (var renderer in renderers)
{if (renderer == null)
{continue;}
renderer.sharedMaterials = new Material[renderer.sharedMaterials.Length];
}
/* var animator = model.GetComponent<Animator>();
if(animator!=null) Object.DestroyImmediate(animator);*/
}
A1:我这边试验过,不会变回来啊,会不会是把工程回滚了。另外这个脚本的 ReimportAllModel 只对自身就没有勾选 Import Materials 的模型无效。
感激 Prin@UWA 问答社区提供了答复
A2:尝试屡次,发现关掉 Cache Server 就好了。
感激题主唐 @UWA 问答社区提供了答复
Editor
Q:我有个需要就是要将关卡里的对象通过脚本间接创立,而不是间接将 Prefab 拖到场景中。因而我须要能象 MeshRenderer 那样间接在场景中显示并不便我选中与编辑的。
代码相似这样:
public class SpawnPrefab : MonoBehaviour
{
public GameObject prefabEntity;
void Start()
{Instantiate(prefabEntity);
}
}
MeshRenderer 有上面两个个性:
1. 在 Editor 模式下 SceneView 与 GameView 上面同时显示;
2. 在运行模式下绘制出的对象能够在 SceneView 下选中。
目前我是在 OnDrawGizmos 函数中调用 Graphics.DrawMesh,但 SceneView 中却无奈选中,在 Update 中绘制却在 Editor 模式下无奈显示。我感觉如同尝试的方向错了。
A:OnDrawGizmos 外面绘制显然是不行的,这个函数在打包进去 Runtime 都不会调用。
要在 SceneView 中选中编辑,肯定得是场景中的某个 GameObject。(用 GameObject 挂 MeshRenderer 必定能满足“SceneView 编辑”和“运行时脚本创立”两个需要的。)
如果题主的需要是肯定要用 Graphics 的立刻渲染接口来画 Mesh,并且要在 Editor 下显示,那么给类加一个 ExecuteAlways 属性就能够了,只是还不能在 SceneView 中选中编辑。
如果还想实现 Scene 窗口下编辑性能,只能给要绘制的 Mesh 绑定一个场景中挂了 MeshRenderer 的 GameObject。Graphics.DrawMesh 绘制物体的 Transform 与这个 GameObject 保持一致就行了。如下图,Game 窗口为 OnPostRender 函数中用 Graphics.DrawMeshNow 函数绘制的成果,Scene 窗口中为绑定的用来编辑调整的物体,两者的 Transform 是统一的:
要害代码如下:
感激 Prin@UWA 问答社区提供了答复
UGUI
Q:对于动静加载 Item,这样是不是算是交叉了,如果有大量的 Item 那得多少 DrawCall,我感觉我走入了误区,求解如何学习这方面,还是说理论工作中,都不去管这种?
我这里只是举了个例子,失常我的项目中元素不可能这么少,如果多,动静加载的如何合批?如果要独自写脚本来解决动静加载的 Item 中的元素,那可就太不合理了。例如 NGUI 应用过 Depth 来控制面板下元素的合批,我只理解 UGUI 是用摆放程序来管制,如果只是这样,对动静加载的太不敌对了。
A1:共享雷同材质的网格,满足其它合批条件,以相邻程序渲染即可合批,缩小 DrawCall。所以合批的要害,在于对应用雷同材质的物体,管制渲染程序。
合批条件和优化计划有以下材料:
https://blog.uwa4d.com/archives/optimzation_cpu.html
https://docs.unity3d.com/Manual/DrawCallBatching.htmlUnity 中影响渲染程序的因素:
https://zhuanlan.zhihu.com/p/55762351不同的资源管制渲染程序的形式不同,如 MeshRenderer,能够设置材质的 RenderQueue;ParticleSystem 能够设置 Order In Layer 和 Sorting Layer 等。
UGUI 元素的渲染程序是 UGUI 这个插件自身决定的,咱们要做的是了解 UGUI 对元素渲染的排序形式,尽可能使雷同材质的 UI 元素以相邻程序渲染。具体的关键点譬如:防止同一层的 UI 元素相互重叠,UGUI 是一层一层绘制的,保障雷同材质的 UI 作为同一层来绘制。如题主我的项目中的 Img 都放在同一层,Txt 都放在第二层。如果两个 Img 产生叠层,就会有一个 Img 是作为第二层来绘制的,导致 Txt 的绘制与 Img 的绘制相互交叉,就会减少 DrawCall。
只有不重叠,应用雷同图集的同层元素就会主动合批的。如果是简单的界面就只能尽可能合并图集,叠层多的状况下,只有保障材质雷同的元素应用雷同图集,并以相邻程序绘制就能够合批。UGUI 里的图集一多,DrawCall 就没什么好方法来管制了。
感激 Prin@UWA 问答社区提供了答复
A2:只有 Item 的面积和另外一个 Item 的面积不重叠,那么所有的文本都算第二层,Image 都算第一层,就 2 个 DrawCall 而已。如果怕被别的 UI 元素影响,能够让这些 Item 独自放在一个 Canvas 外面,这样就不会受到其它 UI 元素的影响了。
感激 Xuan@UWA 问答社区提供了答复
Editor
Q:Loading.CheckConsistency [Editor Only]在编辑器上比拟耗时,请问是做什么的,如何优化?
A:ReadObject 实际上是在加载之后,对 Object 进行反序列化。一个 Prefab 反序列化后,会有大量的 Object。IntegrateAllThreadedObjects 会遍历这些 Object,而 Loading.CheckConsistency 就是在遍历这些 Object 时,对数据进行一致性测验。
所谓一致性测验,就是比方,对下图 Prefab 的序列化文件,会查看两个红框中的 fileID 是否统一。
图片起源:
https://www.cnblogs.com/luguoshuai/p/12323186.html如这篇博文所讲,如果两个 fileID 不统一,会有 CheckConsistency 的报错。
为什么只在 Editor 下进行一致性测验,而打包后 Runtime 不须要测验呢?笔者揣测是在打包的时候曾经对所有对象都测验过了,Runtime 就不须要测验,也防止了测验带来的高耗时。
证据如下图,某次打包的报错堆栈外面,蕴含了 CheckConsistency 的步骤:
图片起源:
https://networm.me/2019/06/23/unity-has-stopped-working/
感激 Prin@UWA 问答社区提供了答复
封面图来源于:Pixel Sorting
https://lab.uwa4d.com/lab/5dd4587f8bab6aaf02db4018
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在 UWA 问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA 学堂:edu.uwa4d.com
官网技术 QQ 群:793972859(原群已满员)