什么是Sprite Kit中的SKSpinLockSync以及如何解决它

时间:2013-10-18 12:00:54

标签: ios objective-c ios7 sprite-kit

我收到的错误报告包含以下堆栈跟踪,我不知道问题是什么。我已经看到这样的建议,这可能是由于在纹理图集中有一个发射器的图像,或者是在添加的同一个运行循环中移除了一个发射器,但我认为这些都不会发生。这是一个零星的问题,我无法再创造它。我只在bug报告中看到它。我很乐意帮忙。

0    libsystem_platform.dylib    OSSpinLockLock + 1
1    SpriteKit   SKSpinLockSync(int*, void ()() block_pointer) + 92
2    SpriteKit   -[SKTexture loadImageData] + 300
3    SpriteKit   -[SKTexture size] + 42
4    SpriteKit   SKCEmitterSprite::update(double) + 3136
5    SpriteKit   SKCSprite::update(double) + 354
6    SpriteKit   SKCSprite::update(double) + 354
7    SpriteKit   -[SKScene _update:] + 174
8    SpriteKit   -[SKView(Private) _update:] + 324
9    SpriteKit   -[SKView renderCallback:] + 820
10   SpriteKit   __29-[SKView setUpRenderCallback]_block_invoke + 130
11   SpriteKit   -[SKDisplayLink _callbackForNextFrame:] + 254
12   QuartzCore  CA::Display::DisplayLinkItem::dispatch() + 98
13   QuartzCore  CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 344
14   IOMobileFramebuffer     IOMobileFramebufferVsyncNotifyFunc + 104
15   IOKit   IODispatchCalloutFromCFMessage + 248
16 ...   CoreFoundation  __CFMachPortPerform + 136
17   CoreFoundation  __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 34
18   CoreFoundation  __CFRunLoopDoSource1 + 346
19   CoreFoundation  __CFRunLoopRun + 1406
20   CoreFoundation  CFRunLoopRunSpecific + 524
21   CoreFoundation  CFRunLoopRunInMode + 106
22   GraphicsServices    GSEventRunModal + 138
23   UIKit   UIApplicationMain + 1136
24   myApplication  main.m line 16  main
编辑:我现在意识到我在几种不同的情况下得到了SKSpinLockSync问题,并不总是与发射器有关。我认为我经常使用发射器看到它的唯一原因是因为这是应用程序中图像加载的狮子份额,所以它只是统计上最可能的。堆栈跟踪的前四行始终相同。所以,最多包括[SKTexture Size]

7 个答案:

答案 0 :(得分:5)

我遇到了同样的问题,当我打电话时发现了

NSString *p = [[NSBundle mainBundle] pathForResource:name ofType:@"sks"];  
SKEmitterNode *e = [NSKeyedUnarchiver unarchiveObjectWithFile:p];  

很多次,它将使用相同的崩溃日志随机崩溃应用程序

SKSpinLockSync(int*, void ()() block_pointer) + 36  
-[SKTexture loadImageData] + 252  
-[SKTexture size] + 44  
SKCEmitterSprite::update(double) + 2928  

我认为这是Sprite Kit的问题,希望Apple能尽快解决这个问题

我的解决方案是:每次都不要调用unarchiveObjectWithFile

unarchiveObjectWithFile可能与IO有关,如果您经常像游戏中的每个帧那样执行此操作,或者SKTexture缓存系统出现问题时需要纹理数据并在非线程安全中调用loadImageData,则可能会崩溃。 / p>

所以我重复使用SKEmitterNode,这是我的函数

// Emitter Pool
- (SKEmitterNode*)getEmitter:(NSString*)name {
    if(!mDictEmitter)
        self.mDictEmitter = [NSMutableDictionary new];
    SKEmitterNode *e = [mDictEmitter objectForKey:name];
    if(!e){
        NSString *p = [[NSBundle mainBundle] pathForResource:name ofType:@"sks"];
        e = [NSKeyedUnarchiver unarchiveObjectWithFile:p];
        [mDictEmitter setObject:e forKey:name];
    }
    return [e copy];
}

答案 1 :(得分:2)

OSSpinLock是一种确保多线程应用程序中的原子操作的机制。

我不认为这里存在多线程问题,而是loadImageData可能提供了在工作的原子部分崩溃的数据。这可能是由于包中缺少(或损坏或不支持的文件格式)纹理。它肯定是一个导致纹理加载失败的发射器。

尝试在发布配置中测试您的应用(编辑方案)一段时间。一些错误仅在启用了优化的发布版本中浮出水面。您还可以构建应用程序的特殊版本并将其部署到您的设备并进行测试。您现在的第一个目标应该是在您自己的设备上验证问题,否则可能很难确定。

调用堆栈确实给你一些提示:问题在于发射器是精灵的子节点,它是另一个精灵的子节点,它是场景的子节点。也许这会缩小它。

答案 2 :(得分:2)

我在类似的情况下遇到了相同的崩溃,并且能够解决它

就我而言,我试图通过SKAction播放图像序列:

[SKAction animateWithTextures: timePerFrame:]

我不确定原因是什么,但我的预感是它与未预加载的纹理有关。该方法的文档没有提供关于它们是否必须预先加载的任何见解,因此它纯粹是猜想,但是从我收集的内容SpriteKit看起来似乎很窒息,因为它无法快速加载图像以显示它们。

无论如何,使用[SKTexture preloadTextures:...可以完全解决我的崩溃问题

希望它也能帮助你和其他人!

答案 3 :(得分:0)

我在使用SpriteKit制作游戏时遇到了类似的问题。所有能够从互联网搜索获得的帖子都无法解决。有时,如果操作包含多线程的概念,则特殊操作类型将导致此问题,而不是由于包中的损坏或缺少纹理。我确实解决了!换句话说,间接你的代码可能有一种多线程,即使看起来没有明显的多线程。

答案 4 :(得分:0)

我在Sprite Kit中遇到了这个问题(同一个崩溃日志堆栈)。我在很多时间内尝试了很多东西 - 最后想出来了,排序:它似乎是因为源纹理位于Texture Atlas文件夹中,并且它没有相应的@ 2x图像。尝试将纹理移出纹理图集和/或添加图像的@ 2x版本。

答案 5 :(得分:0)

如果使用SKEmitterNode并同时创建1个以上(大约在同一时间关闭),我的游戏仍然会崩溃。我不得不手动预加载(创建并添加发射器到场景),然后我能够防止崩溃我必须让粒子效果被创建并添加到场景中并让它运行它的动作。然后我将粒子alpha设置为0,以隐藏它。到那时我被失望了,我预装了一切。

使用上面的SKEmitterNodegetEmitter方法,当我在同一时间创建多个发射器时,我仍然会崩溃。我通过在开始时创建一个粒子,将其添加到场景中,并将其alpha设置为0来解决这个问题。这是一种愚蠢的方式并且它会爆炸,但它起作用并且不会崩溃。

示例:

@implementation MyGameScene

- (instancetype)initWithSize:(CGSize)size
{
    if(self = [super initWithSize:size]){
        HitEmitter *emitter = [HitEmitter particle]; // class method use getEmitter method
        [self addChild:emitter];
        [emitter setName:@"temp"];
        [emitter setAlpha:0];

        // add a second timer to remove it.
        [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(removeEmitter) userInfo:nil repeats:NO];
    } return self;
}

答案 6 :(得分:-1)

我正在构建一个Spritekit应用程序。该应用程序不规则地崩溃,没有调试信息只留下指向可怕的SKSpinLockLock的指针。该应用程序在一组复杂的“动画”动作中崩溃。就像R.Randazzo在他的帖子中提到的那样,懒惰的图像加载可能会导致这些问题。但我的所有动画都使用预装的图像。最终我发现了一个懒惰的加载图像“隐藏在阴影中”,等待作为我的动画序列和用户交互的结果呈现。在预加载此图像后,SKSpinLockLock鬼魂也消失了。注:我正在为IOS 7 +开发