深度调整阶段位于Container 中的DoFairyBatching()
在Update中触发了 SetRenderingOrder(context);
若该容器开启了深度调整 且在当时阶段需要做合批处理设置了 _fBatchingRequested
即会触发DoFairyBatching()
对组件的深度调整逻辑就发生在 DoFairyBatching()阶段
收集容器内子物体
之后对子物体列表做 按相同材质且物体包围盒不存在重叠区域进行排序处理
在此排序操作之后 会把相同材质的物体调整到连续的RenderingOrder值上
使得可以被Unity Dynamic Batching优化
private void SetRenderingOrder(UpdateContext context)
{
if (_fBatchingRequested)
DoFairyBatching();
if (_mask != null)
_mask.renderingOrder = context.renderingOrder++;
int cnt = _descendants.Count;
for (int i = 0; i < cnt; i++)
{
DisplayObject child = _descendants[i];
if (child != _mask)
{
int order = context.renderingOrder++;
if (!_setNativeChildrenOrderByDepth)
{
child.renderingOrder = order;
}
else
{
child.renderingOrder = 0;
Vector3 pos = child.cachedTransform.localPosition;
child.cachedTransform.localPosition = new Vector3(pos.x, pos.y, 0 - order);
}
}
if ((child is Container) && ((Container)child)._fBatchingRoot)
{
((Container)child).SetChildrenOrderByDepth(_setNativeChildrenOrderByDepth);
((Container)child).SetRenderingOrder(context);
}
}
if (_mask != null)
_mask.graphics._SetStencilEraserOrder(context.renderingOrder++);
}
合批处理算法
private void DoFairyBatching()
{
// 开始做批处理收集
_fBatchingRequested = false;
if (_descendants == null)
_descendants = new List<DisplayObject>();
else
_descendants.Clear();
// 开始收集需要做处理的子物体
CollectChildren(this, false);
// 收集完成
// 做检测算法
int cnt = _descendants.Count;
int i, j, k, m;
object curMat, testMat, lastMat;
DisplayObject current, test;
float[] bound;
for (i = 0; i < cnt; i++)
{
// 当前做检测条件的物体对象
current = _descendants[i];
// 检测物体的 包围盒数据
bound = current._internal_bounds;
// 检测物体的材质
curMat = current.material;
if (curMat == null || current._skipInFairyBatching)
continue;
// k 来记录 收集到的按材质相同分组的位置
k = -1;
// 当前做比较的材质(会更新)
lastMat = null;
// 记录比较时 出现不同材质时 在_descendants中索引位置
m = i;
for (j = i - 1; j >= 0; j--)
{
// 从本物体向前
// 与此current 之前的所有收集物体 做条件检测
// 包括 材质检测 和 包围盒位置检测 是否重叠
// current 前的所有物体
test = _descendants[j];
if (test._skipInFairyBatching)
break;
// 比较的材质
testMat = test.material;
if (testMat != null)
{
// 第一次循环时 lastMat == null 一定会进判断中
// 此时 lastMat 等于当前检测物体的前一项物体的材质
// 且记录下m 需要插入的位置 与前组材质不同的索引位置
// m = j + 1
// 如果currnt 与之前 都相同或者都不相同
// m 都会 = j + 1 也就是 i - 1 + 1 所以有下方的 i != k 时 做移动操作
// 若 current 前 已经存在好几种材质组 m 就会一直更新到更靠前的材质
// 在下方 当取得到和current材质一致的 设置 k = m
// k 即为 要插入到的位置 也为目前该物体列表中相同材质下索引最大的位置
// 材质不同
if (lastMat != testMat)
{
// 当前做比较的材质 替换
lastMat = testMat;
// 记录下 i 之前到最后一项与其材质相同的索引
m = j + 1;
}
// k 是记录 与 curMat 材质相同的
if (curMat == testMat)
k = m;
}
// 比较俩物体的包围盒区域 xMin(取最大) <= (xMax取最小) && yMin(取最大) <= yMax(取最小)
if ((bound[0] > test._internal_bounds[0] ? bound[0] : test._internal_bounds[0])
<= (bound[2] < test._internal_bounds[2] ? bound[2] : test._internal_bounds[2])
&& (bound[1] > test._internal_bounds[1] ? bound[1] : test._internal_bounds[1])
<= (bound[3] < test._internal_bounds[3] ? bound[3] : test._internal_bounds[3]))
{
// 两物体有交集 取消继续比较
// 存在遮挡关系 批处理可能会穿帮 体现不出组件的层级关系 所以不进行
if (k == -1)
k = m;
break;
}
}
// 根据k值 插入新的位置
if (k != -1 && i != k)
{
_descendants.RemoveAt(i);
_descendants.Insert(k, current);
}
}
//Debug.Log("DoFairyBatching " + cnt + "," + this.cachedTransform.GetInstanceID());
}