当SKMutableTexture的窗口被遮挡时,使其他Windows无法响应

时间:2019-06-19 13:29:21

标签: cocoa sprite-kit nswindow sktexture skview

我想使用SpriteKit在一个简单的场景中渲染多个以30fps更新的动态纹理。与CGImage / CALayer组合相比,SKMutableTexture似乎是更好的选择。 SKView有其自己的窗口(因为应该可以随时打开多个不同的视图),它是唯一的子视图。

不幸的是,一旦阻塞了带有SKView的NSWindow,带有NSViews的“主” NSWindow就没有真正的响应能力(事件之间可能是1s)。 我在尝试不同的方法在一个小型演示项目中重新创建滞后时发现,它是在创建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更好的选择?您可以下载项目here(Objective-C代码,但没有关系)。只需尝试在显示/隐藏SKView的文本字段中进行输入即可。

我在以下gif中为文本字段添加了一个简单的0.2s更新,您可以在其中看到滞后: Video showing the lag

1 个答案:

答案 0 :(得分:0)

我会在后台线程中处理纹理,然后在完成后通知主线程该纹理已准备好。

在此示例中,我仅使用了一个可选变量,但是您可以想出更好的方法来通知主线程纹理已准备好

这是在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   
      }

   }
}