UI批量渲染优化

理论上是不会的,因为排序的时候父节点是要保证在子节点之前渲染的。父子节点的渲染顺序是交给用户配置的,见config。如果你配置了父节点在子节点后面那么就会出现你说的问题。

每个节点的renderflag是不会改变的,改变顺序只会改变depthtest。

let parentOpacity = _walker.parentOpacity;
_walker.parentOpacity *= (node._opacity / 255); 这个_walker ?哪里定义的

不知道你看的是哪个版本的引擎。
你全局搜RenderFlow.init就知道了。

哥们有遇到按钮事件不起作用吗

mark

没有啊,这只改渲染和按钮的事件处理没有关系。
你是怎么做的呢,可否提供个demo或者描述下,我看看能不能复现。

只是用了个scrollView ,重用cell,层级复杂了点,然后挂在上面的button点击事件没有响应,话说,config配置,要把那些空节点也写上去,跟实际层级一一对应?

是的,比如a是b的父节点,那么在配置config的时候,b对应的值要大于a的,因为渲染的时候会计算节点的世界坐标,所以要先计算a的坐标,后面计算b的坐标时才是正确的。

mark

方便加个扣扣?

mark

我发你消息了

mark

2.0.9基于楼主的改了一点,设置为这种渲染模式下,conf里没配置的默认为0(因为感觉大部分节点都应该是一个图集可以放一起渲染),label自动后排,这样配置写起了就没有那么繁琐
楼主你看这样有没有什么问题呀?

更新一下,楼主这个的opacity 好像有点Bug,改不动透明度,我在2.0.9的解决了

let childrens = [];
let cqueue = [];
_proto._childrenBatchRender = function(node) {
    node._renderFlag &= ~CHILDREN;
    node._renderFlag |= CHILDREN_BATCH_RENDER;
    let cullingMask = _cullingMask;
    let batcher = _batcher;

let parentOpacity = batcher.parentOpacity;
let opacity = batcher.parentOpacity *= (node._opacity / 255);

let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0;
let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0;
let worldDirtyFlag = worldTransformFlag | worldOpacityFlag;

let config = node.config;
childrens.length = 0;
cqueue.length = 0;
Array.prototype.push.apply(cqueue, node._children);
let ch = null;
node._batcherOpactity = opacity
while(cqueue.length > 0) {
    for(let i = 0, len = cqueue.length; i< len; i++) {
        ch = cqueue.shift();
        if(ch.active) {
          ch._batcherOpactity = ch.parent._batcherOpactity * (ch._opacity / 255)
          ch._color._fastSetA(ch._opacity * ch.parent._batcherOpactity);
          childrens.push(ch);
          Array.prototype.push.apply(cqueue, ch._children);
        }
    }
}
childrens.sort((ch1, ch2) => {
    function _getRenderIndex(node){
        let name = node._name
        // 设置节点排序默认值为0
        let index = 0
        if(config[name]){
            index = config[name]
        }else{
            // 设置Label的Index
            const LabelIndex = cc.Enum({
                NONE: 109,
                BITMAP: 107,
                CHAR: 108,
            });

            const CacheMode = cc.Enum({
                0: "NONE",
                1: "BITMAP",
                2: "CHAR",
            });
            // 自动处理一些label
            if(name.startsWith("Label")){
                let label = node.getComponent(cc.Label)
                if(label){
                    let cacheMode = label.cacheMode
                    index = LabelIndex[CacheMode[cacheMode]]
                }
            }
        }
        return index
    }
    return _getRenderIndex(ch1) - _getRenderIndex(ch2);
});

let children = childrens;
for (let i = 0, l = children.length; i < l; i++) {
  let c = children[i];
  if(c.childrenCount > 0) {
    c._renderFlag &= ~CHILDREN;
  }
  // Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0.
  c._renderFlag |= worldDirtyFlag;
  if (!c._activeInHierarchy || c._opacity === 0) continue;

  // TODO: Maybe has better way to implement cascade opacity
  let colorVal = c._color._val;
  // c._color._fastSetA(c._opacity * opacity);
  flows[c._renderFlag]._func(c);
  if(c.childrenCount > 0) {
    c._renderFlag &= ~CHILDREN;
  }
  c._color._val = colorVal;
    }
    batcher.parentOpacity = parentOpacity;
    this._next._func(node);
}

以前的配置 是全部没注释的,改了就只需要单独把 散图标出来

    let config = {
        // item:0,
        // Node:1,
        // HeadImage:1,
        Sprite_Head:7,
        Sprite_Icon:3,
        // Label_name:6,
        // Label_rank:5,
        // Label_score:5,
    }
1赞

核心就是同层级的ui排一起,只要能正常显示都没问题。我觉得你的想法没问题。
你可以断点到_childrenBatchRender看看节点是不是按你的需求排序的,或者用webgl inspector调试看看是不是一层一层渲染出来的。

mark

战略插眼

mark,然后求分享一下

我在creator编辑器中做了一个很大的额地图,有很多节点,这个该怎么去优化呢,做了自动打包图集还有drawcall四百多呢