【问题标题】:Cocos2d v3 - addChild method make performance problemsCocos2d v3 - addChild 方法使性能问题
【发布时间】:2015-02-05 10:32:28
【问题描述】:

我目前在 cocos2d 3.3 版中的addChild 方法存在性能问题。我目前的情况是我有大约十个CCNode,其中包含一捆其他CCNode(大约500 个),我将这十个称为“大节点”。

“大节点”的孩子有自己的孩子(大约 3 个)。那些 CCNode 是精灵。

“大节点”中的所有子节点都不执行任何操作。一切都发生在他们的更新方法中(如果这相关的话)。

在我的主要场景中,我发现了屏幕上的“大节点”。如果它们是新的“大节点”或旧的在屏幕上不再可见,我运行此代码:

self = mainScene
_allBigNodes = holds all avaible big nodes

        NSMutableArray * childsToRemove = [NSMutableArray arrayWithCapacity: _children.count];

        for(CCNode * child in _children){
            if([child isKindOfClass:[BigNode class]]){
                [childsToRemove addObject:child];
            }
        }

        for(CCNode * child in childsToRemove){
            [child removeFromParentAndCleanup:NO];
        }

        [childsToRemove removeAllObjects];

        for(int BigNodeIndex = _fromBigNodePosition; BigNodeIndex<=_toBigNodePosition; ++BigNodeIndex){

            BigNode * BigNode = [_allBigNodes objectAtIndex: BigNodeIndex];

            [self addChild: BigNode];

        }

主屏幕通常最多有两个孩子。上面的方法效果很好。

关于这个问题:有时在我的游戏中我有一些紧张的动作。所以我用分析工具计算出上面的 addChild 方法的成本在 60-100 毫秒之间。

Running Time    Self                        Symbol Name
90.0ms   79.6%  0.0                         -[CCNode addChild:]
90.0ms   79.6%  0.0                          -[CCNode addChild:z:name:]
89.0ms   78.7%  0.0                           -[CCNode onEnter]
88.0ms   77.8%  0.0                            -[NSArray makeObjectsPerformSelector:]
88.0ms   77.8%  0.0                             -[CCNode onEnter]
72.0ms   63.7%  0.0                              -[NSArray makeObjectsPerformSelector:]
71.0ms   62.8%  0.0                               -[CCNode onEnter]
42.0ms   37.1%  0.0                                -[NSArray makeObjectsPerformSelector:]
42.0ms   37.1%  0.0                                 -[CCNode onEnter]
39.0ms   34.5%  0.0                                  -[CCScheduler scheduleTarget:]
38.0ms   33.6%  2.0                                   PrioritySearch
1.0ms    0.8%   1.0                                   DYLD-STUB$$objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >::grow(unsigned int)
1.0ms    0.8%   0.0                                  -[CCNode physicsNode]
1.0ms    0.8%   0.0                                   -[CCNode physicsNode]
1.0ms    0.8%   1.0                                  objc_msgSend
1.0ms    0.8%   1.0                                  objc_object::sidetable_release(bool)
28.0ms   24.7%  0.0                                -[CCScheduler scheduleTarget:]
26.0ms   23.0%  1.0                                 PrioritySearch
1.0ms    0.8%   0.0                                 -[CCScheduler scheduledTargetForTarget:insert:]
1.0ms    0.8%   1.0                                 DYLD-STUB$$objc_msgSend
1.0ms    0.8%   0.0                                -[CCNode physicsNode]
1.0ms    0.8%   1.0                               DYLD-STUB$$objc_msgSend
16.0ms   14.1%  0.0                              -[CCScheduler scheduleTarget:]
14.0ms   12.3%  0.0                               PrioritySearch
2.0ms    1.7%   0.0                               -[CCScheduler scheduledTargetForTarget:insert:]
1.0ms    0.8%   0.0                            -[CCScheduler scheduleTarget:]
1.0ms    0.8%   1.0                           -[CCNode wasRunning:]

所以我的问题是:有没有办法停用 ccnode,或者什么是处理这种有许多 ccnode 或这些“大节点”不在屏幕上的场景的最佳解决方案?

提前谢谢你

【问题讨论】:

    标签: ios objective-c iphone cocos2d-iphone


    【解决方案1】:

    500 个节点是 很多节点。您不想在运行时添加/删除它们。

    相反,当您不需要它们时,只需更改它们父级的 visiblepaused 属性,以防止它们呈现和运行计划的选择器和操作。

    【讨论】:

    • 我已经实施了您的解决方案。除此之外,我将一个大节点的节点数减少到 50 个。但我在更新方法之间仍有 20-50 毫秒的时间差异。因为我仍然有一些紧张的动作。我分析了应用程序并发现更新方法需要 15% 的 CPU,但例如 CCRender 刷新需要 65% 的 CPU。我以为新版本的cocos2d(版本3)可以处理离屏节点。对吗?
    • 它不会渲染屏幕外节点,但数百个节点仍然会增加相当多的开销,因为仍然必须每帧遍历整个节点图。加上你运行的任何代码。 ;)
    • 好吧,这是有道理的。那么处理这么多节点的最佳方法是什么?这是一款横向卷轴游戏。你有一个好的教程或一个好主意吗?我在这个问题上停留了几天,这或多或少是我游戏中的最后一步。如果你想帮助我,也许我们可以聊天。
    • 通常只有尽可能多的节点同时出现在屏幕上,然后根据需要(即滚动时)更改它们的属性。将其余数据保存在自定义数据结构中。
    • 顺便问一个问题:我目前像这样跟踪时差(正在谈论):long long _lasMilli; -(void) update: (CCTime) dt { long long 毫秒 = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0); if(毫秒 - _lasMilli >= 50){ NSLog(@"%lld", (毫秒 - _lasMilli)); } _lasMilli = 毫秒;这是跟踪时差的可靠方法吗?
    猜你喜欢
    • 2014-05-12
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多