SKMutableTexture делает другие окна не отвечает, когда его окно закрыто - PullRequest
0 голосов
/ 19 июня 2019

Я хочу использовать SpriteKit для рендеринга нескольких динамических текстур, обновляемых со скоростью 30 кадров в секунду в простой сцене.SKMutableTexture кажется лучшим выбором, чем комбинация CGImage / CALayer.SKView имеет свое собственное окно (так как в любое время должно быть открыто несколько разных видов), где оно является единственным подпредставлением.

К сожалению, как только NSWindow с SKView будет закрыто, 'main 'NSWindow с NSViews на самом деле не реагирует (возможно, 1 с между событиями).Пробуя различные способы воссоздания лага в небольшом демонстрационном проекте, я обнаружил, что это происходит, как только я создаю текстуру SKMutableTexture (мне даже не нужно постоянно ссылаться на нее).Мне даже не нужно иметь ни одного узла в моем SKView.Ниже приведен полный код для подкласса SKScene:

@implementation SampleScene
-(void)didMoveToView:(SKView *)view {
    [super didMoveToView:view];

    self.backgroundColor = [NSColor blackColor];
    SKMutableTexture *tex = [[SKMutableTexture alloc] initWithSize:CGSizeMake(10, 10)];
}
@end

Я предполагаю, что SKMutableTexture каким-то образом присоединяет и блокирует NSRunLoop, пока он не будет готов к рисованию.Как только он получает NSWindowDidChangeOcclusionStateNotification, SKView уменьшает частоту обновления, которая влияет на текстуру и, следовательно, цикл выполнения, блокируя ее до тех пор, пока SKView не отрисовывается снова (что, по-видимому, происходит каждую секунду при окклюзии).Я могу обойти это, приостановив SKView, когда окно закрыто, но это не похоже на хорошее решение.

Я что-то не так делаю?Есть ли лучшие варианты, чем использовать SpriteKit для этого варианта использования?Вы можете скачать проект здесь (код Objective-C, но это не имеет значения).Просто попробуйте набрать текстовое поле с SKView видимым / окклюзионным, чтобы проверить его.

Я добавил простое обновление 0.2s для текстового поля в следующем gif, где вы можете увидеть отставание: Video showing the lag

1 Ответ

0 голосов
/ 20 июня 2019

Я бы манипулировал вашей текстурой в фоновом потоке, затем, когда закончил, уведомил основной поток о том, что текстура готова.

В этом примере я использую только необязательную переменную, но вы могли бы придумать лучшие способы уведомить основной поток о том, что ваша текстура готова

Это сделано в Swift:

var generatedTexture : SKTexture?
func generateTexture(){

   DispatchQueue.global(qos: .background).sync{ // we do not want 2 of these to collide with each other
       DispatchQueue.main.async{ 
           generatedTexture = nil   //clear this out to let some other check know something is being generated   
      }
      var newTexture = SKMutableTexture
      while(generatedTexture != nil){}  //freeze the thread in case generatedTexture has not set to nil yet
      //manipulate texture here
      DispatchQueue.main.async{ 
          generatedTexture = newTexture   
      }

   }
}
...