首页 > 解决方案 > Occasional stuttering with SceneKit when touching the screen

问题描述

When I interact with the screen the objects in my game start to stutter. My FPS is at 60 and doesn't drop but the stuttering is still prevalent. I believe my problem is how I'm animating the objects on screen(code below).If anybody could help I would appreciate it.

I have an x amount of nodes inside an array called _activePool. In the Update function I am moving the nodes x position inside _activePool, adding new nodes when the last node in _activePool position is <= 25 and removing the first node in _activePool if it's position is <= -25.

if _cycleIsActive{

            for obj in _activePool{
                //move the obj in _activePool
                obj.position.x += Float(dt * self.speedConstant);
            }

            let lastObj = _activePool.last;

            if (lastObj?.position.x)! + getWidthOfNode(node: lastObj!) + Float(random(min: 15, max: 20)) <= 25{

                // get new obj(pattern) and add to _activePool
                self.getPatternData(sequencePassedIn: selectedSeq, level: self._currentLevel, randomPattern: randomPattern());
            }

            let firstObj = _activePool.first;

            if (firstObj?.position.x)! + getWidthOfNode(node: firstObj!) <= -25{

                // remove object and return to specific pool
                firstObj?.removeFromParentNode();
                returnItems(item: firstObj!);

                _activePool.removeFirst();
            }
        }

I create several arrays and add them to a dictionary

          func activatePools(){
    temp1Pool = ObjectPool(tag: 1, data: []);
    dictPool[(temp1Pool?.tag)!] = temp1Pool;

    temp2Pool = ObjectPool(tag: 2, data: []);
    dictPool[(temp2Pool?.tag)!] = temp2Pool;

    for i in 0... dictPool.count {
         obstacleCreationFactory(factorySwitch: i);
    }

}

Creating my obstacles(enemies)

 func obstacleCreationFactory(factorySwitch: Int){
        Enemies = Enemy();

        switch factorySwitch {
        case 0:
            for _ in 0...100{
                let blueEnemy = Enemies?.makeCopy() as! Enemy
                blueEnemy.geometry = (Enemies?.geometry?.copy() as! SCNGeometry);
                blueEnemy.geometry?.firstMaterial?.diffuse.contents = UIColor.blue;
                blueEnemy.tag = 1;
                temp1Pool?.addItemToPool(item: blueEnemy);

            }
        case 1:
            for _ in 0...100{
                let redEnemy = Enemies?.makeCopy() as! Enemy
                redEnemy.geometry = (Enemies?.geometry?.copy() as! SCNGeometry);
                redEnemy.geometry?.firstMaterial?.diffuse.contents = UIColor.red;
                redEnemy.tag = 2;
                temp2Pool?.addItemToPool(item: redEnemy);
            }
        default:
            print("factory error");
        }
    }

标签: swiftrenderingscenekit

解决方案


如果无法查看您的代码库的其余部分,真的很难猜测是什么导致了您的问题。

如果您在某个地方的某个循环中创建了大量临时对象,您可能会考虑创建一个本地自动释放池以防止内存峰值。是一篇很好的文章,描述了为什么在某些情况下这是一个好主意。

您还可以在计时器或其他东西上调用一些特别昂贵的函数。很难说。

简而言之,您应该考虑使用 Xcode 的 Profiling 工具(称为 Instruments)。具体来说,我建议使用 Time Profiler 来检查哪些函数花费的时间最多并导致这些峰值。

是一个很棒的 WWDC 会议视频,展示了如何使用时间分析器,我建议定期分析您的应用程序,尤其是当您遇到此类问题时。


推荐阅读