在SKSpriteNode的TVOS中设置首选焦点?

由于我在SpriteKit工作,我的button是SKSpriteNodes …但是我发现自己的情况下,我需要通过重写preferredFocusedView在我的viewController设置焦点。 有没有办法将SKSpriteNode向下转换为UIView ? 如果是这样,我还没有能够找出…任何替代scheme?

  let playButton = SKSpriteNode(imageNamed: "PlayButton") playButton.position = CGPoint(x: scene.size.width * 0.25, y: scene.size.height * 0.25) playButton.zPosition = Layer.UI.rawValue scene.worldNode.addChild(playButton) override var preferredFocusedView: UIView? { get { return //playButton how? } } 

现在只有tvOS 10和SpriteKit支持焦点导航,在此之前,您必须使用自己的对焦系统手动进行。 出于这个原因,首选焦点视图已被弃用,因为它只支持UIViews。 您现在应该使用首选的焦点环境。

你要做的第一件事就是在你的GameViewController中把首选焦点环境设置为当前呈现的SKScene。 这基本上意味着你的SKScenes将会处理首选的焦点而不是GameViewController。 在SpriteKit游戏中,SKScenes应该使用SpriteKit API(例如SKLabelNodes,SKSpriteNodes等)来处理诸如button的UI。因此,您需要将首选焦点传递给SKScene。

 class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // default code to present your 1st SKScene. } } #if os(tvOS) extension GameViewController { /// Tell GameViewController that the currently presented SKScene should always be the preferred focus environment override var preferredFocusEnvironments: [UIFocusEnvironment] { if let scene = (view as? SKView)?.scene { return [scene] } return [] } } #endif 

您的playButton应该是SKSpriteNode的一个子类,您将用于游戏中的所有button。 使用枚举,并给他们不同的名称/标识符来区分它们时,他们被按下(结帐苹果示例游戏DemoBots)。

  class Button: SKSpriteNode { var isFocusable = true // easy way to later turn off focus for your buttons eg when overlaying menus etc. /// Can become focused override var canBecomeFocused: Bool { return isFocusable } /// Did update focus override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { if context.previouslyFocusedItem === self { // SKAction to reset focus animation for unfocused button } if context.nextFocusedItem === self { // SKAction to run focus animation for focused button } } } 

与你的SKScenes相比,你可以把焦点环境设置到你的playButton或其他用户界面。

例如开始场景

 class StartScene: SKScene { .... } #if os(tvOS) extension StartScene { override var preferredFocusEnvironments: [UIFocusEnvironment] { return [playButton] } } #endif 

例如GameScene(例如,在需要时将焦点转移到游戏菜单)

 class GameScene: SKScene { .... } #if os(tvOS) extension GameScene { override var preferredFocusEnvironments: [UIFocusEnvironment] { if isGameMenuShowing { // add some check like this return [gameMenuNode] } return [] } } #endif 

当你在SKScenes之间转换时(例如StartScene – > GameScene),你还必须告诉你的GameViewController更新它的焦点环境。 如果您使用SKTransitions,这一点尤为重要,我花了一段时间才弄明白这一点。 如果使用SKTransitions,则在过渡期间旧的和新的场景都处于活动状态,因此GameViewController将使用旧场景首选聚焦环境而不是新场景,这意味着新场景将无法正确聚焦。

每当我在场景之间切换时,我都这样做。 你将不得不稍微延迟,否则将无法正常工作。

  ... view?.presentScene(newScene, transition: ...) #if os(tvOS) newScene.run(SKAction.wait(forDuration: 0.1)) { // wont work without delay newScene.view?.window?.rootViewController?.setNeedsFocusUpdate() newScene.view?.window?.rootViewController?.updateFocusIfNeeded() } #endif 

你应该阅读这篇文章

https://medium.com/folded-plane/tvos-10-getting-started-with-spritekit-and-focus-engine-53d8ef3b34f3#.x5zty39pc

并观看2016年苹果主题演讲,名为“SpriteKit的新特性”,他们在这里谈论了一半。

希望这可以帮助