整理FairyGUI的FairyBatching分析(一)

深度调整阶段位于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());
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在FairyGUI中创建下拉框(ComboBox)时,可以按照以下步骤进行操作: 1. 打开FairyGUI编辑器,并创建一个新的UI页面。 2. 在编辑器的资源列表中,选择一个下拉框组件(ComboBox)并将其拖放到舞台上。 3. 在属性检查器中,可以设置下拉框的大小、位置、默认选项等属性。 4. 右键点击下拉框组件,在弹出的菜单中选择"Edit Items"(编辑项)。 5. 在编辑项界面中,可以添加、删除和编辑下拉框的选项。每个选项由一个文本和一个值组成。你可以设置显示在下拉框中的文本以及对应的值。 6. 在代码中,你可以使用FairyGUI提供的API来操作下拉框。例如,你可以通过`GComboBox`类来获取下拉框实例,并使用`items`属性来设置选项列表,使用`selectedIndex`属性来设置默认选中的索引,使用`value`属性来获取或设置当前选中项的值等。 以下是一个简单的示例代码,展示了如何在FairyGUI中创建和操作下拉框: ```lua local comboBox = UIPackage.CreateObject("包名", "下拉框名") -- 根据实际情况替换"包名"和"下拉框名" comboBox:SetSize(200, 30) comboBox.items = {"选项1", "选项2", "选项3"} comboBox.selectedIndex = 0 comboBox.value = "选项1" comboBox.onChanged:Add(function(context) print("当前选中的值:" .. comboBox.value) end) ``` 在上面的示例中,我们创建了一个名为`comboBox`的下拉框实例。我们设置了三个选项,并将第一个选项作为默认选中项。当选中项发生变化时,会触发`onChanged`事件,并打印当前选中的值。 请注意,上述示例代码是基于Lua语言的FairyGUI API,如果你在其他语言上使用FairyGUI,代码会有所不同。你需要根据具体的开发环境和语言选择相应的API和语法。 希望能对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值