SpriteKit 游戏物理滞后
Posted
技术标签:
【中文标题】SpriteKit 游戏物理滞后【英文标题】:SpriteKit game physics lagging 【发布时间】:2014-09-20 10:42:25 【问题描述】:我从事 SpriteKit 游戏已经有一段时间了,但我遇到了一个无法摆脱的烦人问题。我不想过多介绍游戏,但它非常简单。我使用 SpriteKits 物理每秒生成一些从屏幕顶部落下的对象 (SKSpriteNodes),并且玩家正在与它们进行交互。
大部分时间游戏运行完美(恒定 60 FPS)。问题是有时(可能每分钟一次或类似的情况),游戏开始滞后约 3-5 秒(仍为 60 FPS),然后它再次完美运行(注意:我正在运行iPhone 5s 上的游戏)。这似乎是因为物理,因为如果我在一个对象上添加一个正常的移动动作,它会运行得非常顺利,而受物理影响的节点是滞后的。
我尝试移除我拥有的一些粒子和效果并重复使用我的对象,但我无法移除延迟。我决定创建一个非常简单的测试项目,看看滞后是否会消失,但它仍然存在。代码如下:
#import "GameScene.h"
static const uint32_t groundCategory = 1 << 0;
static const uint32_t objectCategory = 1 << 1;
@implementation GameScene
-(void)didMoveToView:(SKView *)view
// Init
self.backgroundColor = [UIColor blackColor];
self.physicsWorld.gravity = CGVectorMake(0.0f, -3.2f);
self.physicsWorld.contactDelegate = self;
// Ground
SKPhysicsBody* ground = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(0, -88) toPoint:CGPointMake(self.size.width, -88)];
ground.categoryBitMask = groundCategory;
self.physicsBody = ground;
// Start game loop
SKAction* waitAction = [SKAction waitForDuration:1];
SKAction* sequence = [SKAction sequence:@[[SKAction performSelector:@selector(addObject) onTarget:self], waitAction]];
SKAction* repeatAction = [SKAction repeatActionForever:sequence];
[self runAction:repeatAction withKey:@"fallingObjectsAction"];
- (void)addObject
SKSpriteNode* newObject = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(88, 88)];
newObject.name = @"Object";
newObject.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:newObject.size];
newObject.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height + newObject.size.height);
newObject.physicsBody.categoryBitMask = objectCategory;
newObject.physicsBody.contactTestBitMask = groundCategory;
newObject.physicsBody.collisionBitMask = 0;
[self addChild:newObject];
- (void)didBeginContact:(SKPhysicsContact *)contact
if ([contact.bodyA.node.name isEqualToString:@"Object"])
[contact.bodyA.node removeFromParent];
else if ([contact.bodyB.node.name isEqualToString:@"Object"])
[contact.bodyB.node removeFromParent];
@end
我每秒生成一个对象并让它从屏幕顶部落下。当它撞到地面时,它会被移除。
是我使用了物理错误还是 SpriteKit 的错误导致它滞后?这似乎很奇怪,因为我正在使用带有 ios 8 的 iPhone 5s 运行一个非常简单的项目。
【问题讨论】:
您是如何确定游戏在滞后时仍以 60 fps 运行的?您是否使用了 drawsFPS 和其他标志? CPU 使用率(请参阅 Xcode Debug Navigator 选项卡)何时滞后以及何时不滞后? 在viewController中,我设置了skView.showsFPS = YES; CPU 使用率(对于我发布代码的测试项目)不滞后时为 11%,滞后时为 11%,因此没有区别。 听起来滞后是另外一回事,例如,如果您尝试使用移动动作移动启用物理的节点,这将与物理冲突 我不知道它是什么。我试图通过在更新方法中更改它们的位置来关闭重力并手动移动对象,并且始终可以完美运行。但我不想那样解决。 【参考方案1】:好的,我在物理方面也遇到了同样的问题。问题是尽管 CPU 使用率低且 FPS 一致,但对象仍会抖动。我终于知道为什么了。我找到的解决方案是不要将physicsWorld.speed 设置为1.0;将其设置为 .9999。现在一切顺利。
我希望这会有所帮助。
【讨论】:
即使调试器读取 60 fps,我的游戏也出现抖动,这解决了我的问题。我想知道这是否是Apple的错误?不管怎样,你为我省去了很多麻烦。 根据其他线程中的评论 (***.com/questions/36011362/…) SpriteKit 物理引擎计算始终与帧速率相关联,这意味着即使有是一个非常小的 fps 下降,所以不幸的是,如果你使用 spritekit 的物理引擎,现在似乎没有 100% 的工作方法可以完美地解决这个问题。您能做的最好的事情是尽可能优化您的更新方法,或者根本不使用 spritekit 的物理引擎。以上是关于SpriteKit 游戏物理滞后的主要内容,如果未能解决你的问题,请参考以下文章
使用物理 SKSpriteNode 子级暂停 SpriteKit 游戏
调用函数 touchesBegan 时 SpriteKit 游戏延迟