Controlling Input on tvOS

Users can connect game controllers to Apple TV just as they do with iOS devices. When a game controller is connected to an Apple TV, the controller can also be used to navigate the user interface. Low-level controller inputs are automatically turned into higher-level events that are delivered through the responder chain. If your app relies solely on UIKit and focus interactions, you don’t need to do any work to support Game Controllers. Whether or not a user is using an Siri Remote or a game controller is transparently handled for you by tvOS.

There are a couple of significant changes to the Game Controller framework on Apple TV:

Controller Limits

A maximum of four game controllers (plus one Siri Remote) can be connected to an Apple TV at any given time. Your game designs should keep these limitations in mind.

Using the Siri Remote as a Game Controller

The Siri Remote can act as a micro gamepad, and is great for games that require simple or motion based input. As with other controllers, it shows up in the Game Controller framework as a GCController object. The remote supports both the GCMotion and the GCMicroGamepad profiles. The micro gamepad profile is supported only by the Siri Remote; to support other game controllers, you must also implement the extended gamepad profile.

The controller has the following characteristics:

Determining the Destination of Controller Input

The default behavior in UIKIt on tvOS is to process all low-level controller inputs and deliver high-level events to the responder chain. Low-level game controller inputs are not available by default, because all of the events are processed by UIKit. When you want to read controller input directly, you need to turn off UIKit’s behavior. Controller input destination shows the two input paths.

Figure 4-1  Controller input destination

For example, a common design for many games is to have one view that displays a main menu of options, and a second view that presents gameplay. The main menu could be implemented using UIKit elements so that its behavior is consistent with focus behavior. When the gameplay view is presented, you would use the Game Controller framework to turn off the UIKit behavior controller input process in order to directly read the controller input.

If you plan to use the Game Controller framework to read low-level inputs, you need to use GCEventViewController (or a subclass) to display your game content. By default, whenever the GCEventViewController object’s view or a subview is the first responder, then game controller input is captured by the view controller and delivered to your app through the Game Controller framework. Events are not delivered to UIKit. When a view that is not in the view controller’s hierarchy is the first responder, then events are processed normally by UIKit.

Once you have a GCEventViewControllerobject in your responder chain, you can also use its controllerUserInteractionEnabled property to toggle where events are sent. For example, if your game mixes UIKit content on menu screens with Metal content as part of the game view, then when the game is paused, you would change the value of the controllerUserInteractionEnabled property to enable UIKit interaction. In this case, one of your menu items needs to be a button that resumes gameplay, because your controller’s pause handler will no longer be called. When this menu item is selected, you would switch the event handling back to game controllers and resume your game.

If for some reason you cannot use a GCEventViewController object to control how events are propagated, you can implement this behavior yourself in your game. To do this, override the pressesBegan:withEvent: method (as well as the other event handlers for press events) in your view or view controller. If you want a particular event to be delivered to UIKit, call the super class’s implementation of the method. If you want it to only be processed by the game controller framework, do not call the superclass.