https://v.qq.com/x/page/l0329fvbrfn.html
https://blog.uwa4d.com/archives/fillrate.html
https://v.qq.com/x/page/e0520qxtjox.html
- 重叠UGUI组件会增加DrawCall
尽量减少UGUI组件重叠 尽量使用相同的材质 - mask组件会增加DrawCalll
mask写模板缓存会增加一个DrawCall mask组件子节点下面原来可合并的材质也变得不可合并 - 尽可能把文字设置在图片以上
合并文字DrawCall - 边框Image的ImageType一般为Sliced 将FillCenter设置为为false可降低OverDrall
- Empty4Raycast 需要使用Image的Raycast事件又不想产生Image造成的OverDrall
using UnityEngine;
using System.Collections;
namespace UnityEngine.UI {
public class Empty4Raycast : MaskableGraphic {
protected Empty4Raycast() {
useLegacyMeshGeneration = false;
}
protected override void OnPopulateMesh(VertexHelper toFill) {
toFill.Clear();
}
}
}
- PolygonImage 类似第四条 不仅个角 可以把Image的顶点挖出来 减少渲染面积 例圆形
using System.Collections.Generic;
namespace UnityEngine.UI {
[AddComponentMenu("UI/Effects/PolygonImage", 16)]
[RequireComponent(typeof(Image))]
public class PolygonImage : BaseMeshEffect {
protected PolygonImage() { }
// GC Friendly
private static Vector3[] fourCorners = new Vector3[4];
private static UIVertex vertice = new UIVertex();
private RectTransform rectTransform = null;
private Image image = null;
public override void ModifyMesh(VertexHelper vh) {
if (!isActiveAndEnabled) return;
if (rectTransform == null) {
rectTransform = GetComponent<RectTransform>();
}
if (image == null) {
image = GetComponent<Image>();
}
if (image.type != Image.Type.Simple) {
return;
}
Sprite sprite = image.overrideSprite;
if (sprite == null || sprite.triangles.Length == 6) {
// only 2 triangles
return;
}
// Kanglai: at first I copy codes from Image.GetDrawingDimensions
// to calculate Image's dimensions. But now for easy to read, I just take usage of corners.
if (vh.currentVertCount != 4) {
return;
}
rectTransform.GetLocalCorners(fourCorners);
// Kanglai: recalculate vertices from Sprite!
int len = sprite.vertices.Length;
var vertices = new List<UIVertex>(len);
Vector2 Center = sprite.bounds.center;
Vector2 invExtend = new Vector2(1 / sprite.bounds.size.x, 1 / sprite.bounds.size.y);
for (int i = 0; i < len; i++) {
// normalize
float x = (sprite.vertices[i].x - Center.x) * invExtend.x + 0.5f;
float y = (sprite.vertices[i].y - Center.y) * invExtend.y + 0.5f;
// lerp to position
vertice.position = new Vector2(Mathf.Lerp(fourCorners[0].x, fourCorners[2].x, x), Mathf.Lerp(fourCorners[0].y, fourCorners[2].y, y));
vertice.color = image.color;
vertice.uv0 = sprite.uv[i];
vertices.Add(vertice);
}
len = sprite.triangles.Length;
var triangles = new List<int>(len);
for (int i = 0; i < len; i++) {
triangles.Add(sprite.triangles[i]);
}
vh.Clear();
vh.AddUIVertexStream(vertices, triangles);
}
}
}
- 事件检测优化 UI组件不需要事件检测时 关闭Ratcast选项
例 修改Image组件源码 默认关闭Raycast - 动态组件分离
动态组建单独放在一个canvas下 防止合并顶点时对静态组件的重复操作
对于一直处于运动的UGUI组件 合并增加canvas组件
对于游戏过程中可能运动的组件 通过脚本动态添加canvas组件(记得销毁) - Image组件中的color是顶点色 通过动画改变时也会对顶点产生影响
- 5.2以后 canvas.bulidbatch被分离到多线程(WaitingForJob PutGeometryJobFence BatchRenderer.Flush)里面 (所以profile里面可能看不出)
- 不需要的动画可禁用 减小开销
- 尽量少用UIEffect (Outline Shadow) 尤其是文字 会增加大量顶点
- z值不同将不会合并DrawCall
- ImageSprite为空或者Color.a=0时仍会渲染(scale=0将不渲染)
- position赋值 即使数值没有变化也会重建网格(增加阈值判断)
- 隐藏UI可以通过设置layermask 可以防止网格重建
- 可将部分UI渲染到rt 减少drawcall