Что такое 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 +