Что такое SKSpinLockSync в Sprite Kit и как мне это исправить

Я получаю сообщение об ошибке со следующей трассировкой стека, и я не знаю, в чем проблема. Я видел предположения, что это может быть вызвано наличием изображения эмиттера в атласе текстуры или удалением эмиттера в том же цикле выполнения, в котором он был добавлен, но я не думаю, что что-то из этого происходит. Это спорадическая проблема, и я не могу ее воссоздать. Я вижу это только в сообщениях об ошибках. Я хотел бы любую помощь.

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 ответов

У меня была такая же проблема, и я обнаружил, что когда я звоню

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 в не поточно-безопасном режиме.

Поэтому я снова использую 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];
}

OSSpinLock - это механизм для обеспечения атомарных операций в многопоточных приложениях.

Я не думаю, что здесь есть проблема с многопоточностью, скорее, loadImageData, возможно, предоставила данные, которые вылетали во время атомарной части работы. Это может быть связано с отсутствующей (или поврежденным или неподдерживаемым форматом файла) текстурой в комплекте. Это, конечно, излучатель, который приводит к сбою загрузки текстуры.

Попробуйте протестировать ваше приложение в конфигурации выпуска (отредактируйте схему) некоторое время. Некоторые ошибки только появляются в сборках релизов с включенными оптимизациями. Вы также можете создать временную версию своего приложения, развернуть ее на своем устройстве и протестировать. Ваша первая цель сейчас должна состоять в том, чтобы проверить проблему на вашем собственном устройстве, иначе это может быть трудно определить.

Стек вызовов дает вам несколько советов: проблема в эмиттере, который является дочерним элементом спрайта, который является дочерним элементом другого спрайта, который является дочерним элементом сцены. Возможно, это сужает это.

Я испытал тот же сбой в аналогичном случае и смог решить его

В моем случае я пытался воспроизвести последовательность изображений через SKAction:

[SKAction animateWithTextures: timePerFrame:]

Я не уверен, в чем причина, но я догадываюсь, что это связано с тем, что текстуры не были предварительно загружены. Документация по методу не дает никакого представления о том, должны ли они быть предварительно загружены, так что это чисто предположение, но из того, что я собираю, SpriteKit, кажется, задыхается, потому что не может загрузить изображения достаточно быстро, чтобы отобразить их.

в любом случае, используя [SKTexture preloadTextures:... решает мою аварию полностью

надеюсь, что это поможет вам и другим тоже!

При использовании SKEmitterNode и создать более 1 одновременно (закрыть в то же время), моя игра по-прежнему зависала. Мне пришлось вручную предварительно загружать (создавать и добавлять эмиттер в сцену), и к тому времени я смог предотвратить сбой, мне пришлось позволить создать эффект частицы, добавить его в сцену и запустить его действие. Затем я устанавливаю альфа частицы на 0, чтобы скрыть это. К тому времени я был К разочарованию, я предварительно загрузил все.

С помощью SKEmitterNode а также getEmitter описанным выше способом, я все еще получаю сбои, когда я создаю более одного излучателя в одно и то же время. Я решаю это, создавая одну из частиц в начале, добавляю ее к сцене и устанавливаю ее 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;
}

У меня была похожая проблема при создании игры с использованием SpriteKit. Все сообщения, которые можно было получить из поиска в Интернете, были недействительными для решения. Иногда специальный тип действия может вызвать эту проблему, а не из-за поврежденной или отсутствующей текстуры в комплекте, если действие содержит концепцию многопоточности. И я это решил! Другими словами, косвенно ваш код может иметь вид многопоточности, даже если кажется, что нет явных многопотоков.

У меня была именно эта проблема (тот же стек журналов аварий) с частицами в Sprite Kit. Я перепробовал много вещей за много часов - и, наконец, понял, что-то вроде: потому что исходная текстура находилась в папке Texture Atlas, и у нее не было соответствующего изображения @2x. Попробуйте переместить текстуру из текстурного атласа и / или добавить @2x версию изображения.

Я создаю приложение Spritekit. Приложение нерегулярно зависало без отладочной информации, оставляя только указатель на страшный SKSpinLockLock. Приложение упало в середине сложного набора "анимационных" действий. Как упоминал Р.Рандаццо в своем посте, ленивая загрузка изображений может вызвать эти проблемы. Но все мои анимации используют предварительно загруженные изображения. В конце концов я обнаружил ленивое изображение загрузки, "прячущееся в тени", ожидающее представления в результате моей последовательности анимации и взаимодействия с пользователем. После предварительной загрузки этого изображения призрак SKSpinLockLock исчез. NB я разрабатываю для IOS 7 +

Другие вопросы по тегам