cocos cc.find和getChildByName getChildByUuid三个接口的剖析比较

本文对比分析了Cocos Creator中cc.find、getChildByName及getChildByUuid三种子节点获取方法的效率。cc.find适用于层级路径查找,但不推荐每帧调用;getChildByName与getChildByUuid直接在子节点中搜索,效率更高。文章建议合理布局节点树以提升性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cc.find 和getChildByName 都可以获取子节点

# 今天我们来探究一下这三个方法的效率

首先我们先阅读一下官方文档中cc.findgetChildByName
getChildByUuid这三个方法有关的知识。

在官方文档中给出的find API描述是这样的。

Finds a node by hierarchy path, the path is case-sensitive. It will traverse the hierarchy by splitting the path using ‘/’ character. This function will still returns the node even if it is inactive. It is recommended to not use this function every frame instead cache the result at startup.
翻译过来是:
通过一个具有层次的且大小写敏感的路径来查找一个节点。它将通过使用‘/’字符分割路径来遍历层次结构。甚至这个节点是未激活的,这个方法也可以将它获取并返回。启动时每一帧都要写入缓存,建议不要在这个时候使用该方法。

在官方文档中给出的getChildByName 、getChildByUuid API描述就不贴了 很简单。
因为引擎的开源,我们似乎可以看到,每个接口的具体实现,现在我们来研究一下。
在位于cocos-creator/engine/cocos2d/core/utils/find.js 中:

// cc.find
@method find
 * @static
 * @param {String} path
 * @param {Node} [referenceNode]
 * @return {Node|null} the node or null if not found
 */
cc.find = module.exports = function (path, referenceNode) {
    if (path == null) {//判断路径是否为空
        cc.errorID(5600);
        return null;
    }
    if (!referenceNode) {//判断参考节点是否为空
        var scene = cc.director.getScene();//获取当前场景
        if (!scene) {
            if (CC_DEV) {
                cc.warnID(5601);
            }
            return null;
        }
        else if (CC_DEV && !scene.isValid) {//判断该场景是否未被destory
            cc.warnID(5602);
            return null;
        }
        referenceNode = scene;
    }
    else if (CC_DEV && !referenceNode.isValid) {
        cc.warnID(5603);
        return null;
    }

    var match = referenceNode;
    var startIndex = (path[0] !== '/') ? 0 : 1; // skip first '/'
    var nameList = path.split('/');

    // parse path //循环嵌套
    for (var n = startIndex; n < nameList.length; n++) {
        var name = nameList[n];
        var children = match._children;
        match = null;
        for (var t = 0, len = children.length; t < len; ++t) {
            var subChild = children[t];
            if (subChild.name === name) {
                match = subChild;
                break;
            }
        }
        if (!match) {
            return null;
        }
    }

    return match;
};

在位于cocos-creator/engine/cocos2d/core/utils/base-node.js 中:

/**
     * !#en Returns a child from the container given its name.
     * !#zh 通过名称获取节点的子节点。
     * @method getChildByName
     * @param {String} name - A name to find the child node.
     * @return {Node} a CCNode object whose name equals to the input parameter
     * @example
     * var child = node.getChildByName("Test Node");
     */
    getChildByName (name) {
        if (!name) {
            cc.log("Invalid name");
            return null;
        }

        var locChildren = this._children;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            if (locChildren[i]._name === name)
                return locChildren[i];
        }
        return null;
    },
/**
     * !#en Returns a child from the container given its uuid.
     * !#zh 通过 uuid 获取节点的子节点。
     * @method getChildByUuid
     * @param {String} uuid - The uuid to find the child node.
     * @return {Node} a Node whose uuid equals to the input parameter
     * @example
     * var child = node.getChildByUuid(uuid);
     */
    getChildByUuid (uuid) {
        if (!uuid) {
            cc.log("Invalid uuid");
            return null;
        }

        var locChildren = this._children;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            if (locChildren[i]._id === uuid)
                return locChildren[i];
        }
        return null;
    },

这么一看,在相同情况下都只取下一级的子节点。后两者的运算量要小于前者。
其实总的来看 ,cc.find 尽量不要用在查找路径比较深的节点,不然会增加它的时间复杂度,这里我们可以采取存储中间节点的办法 来缩短它的路径,用内存换性能。
当然如果一个节点下方的子节点太多,也会影响这些方法的使用性能。所以 我们在构建节点树时,也要合理布局。

[PreviewInEditor] Cannot read properties of null (reading 'addComponent') TypeError: Cannot read properties of null (reading 'addComponent') at Main.onLoad (file:///F:/%E8%AF%95%E7%8E%A9/test/temp/programming/packer-driver/targets/editor/chunks/00/00bd30f7c8a173f23ca3102f87e5c0fef2855b8b.js:248:72) at eval (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:45186:132) at OneOffInvoker.eval [as _invoke] (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:42027:9) at OneOffInvoker.invoke (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:42141:16) at NodeActivator.activateNode (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:45237:27) at Scene._activate (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:51517:44) at Director.runSceneImmediate (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:19203:17) at C:\ProgramData\cocos\editors\Creator\3.8.5\resources\app.asar\builtin\scene\dist\script\3d\manager\scene\utils.ccc:1:1367 at eval (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:114435:17) at eval (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:122014:9) at eval (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\resources\3d\engine\bin\.cache\dev\editor\bundled\index.js:243205:9) at sentryWrapped (C:\ProgramData\cocos\editors\Creator\3.8.5\resources\app.asar\node_modules\src\helpers.ts:100:17)
最新发布
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值