Notes from WWDC 2015: Playing in a GameplayKit Wonderland
Apple's new GameplayKit framework debuted at WWDC 2015. It is part of Apple's ongoing work to consolidate gaming under a native framework umbrella. GameplayKit joins SpriteKit, SceneKit, and Metal, an evolving suite that's marked by Apple-sourced APIs deployed to Apple-specific destinations.
The GameplayKit framework consists of sixteen classes. These are split fairly evenly between game-logic support and autonomous agent gaming. The former enables you to create state machines and min-max-optimized strategies. The latter builds smart goal-oriented agents that optimize their behaviors in constrained environments.
If this sounds a bit abstract, it is. GameplayKit lives entirely in the model world of model-view-controller. It provides no UI specifics or physicality apart from the numbers that drive its model. You can tie the semantics it generates into SpriteKit and SceneKit visualizations or even to UIKit layouts however you wish.
Like UIKit's dynamic view animations, these APIs don't just support gaming. The fun agent-based updates can easily be used in any interface. They can introduce liveliness to dialogs, forms, and other UI elements. When adding a button to a display, why not have the other labels and text fields use a "flee pattern" to make room for the new element, for example?
Of course, if you're only focused on "how can this work in traditional interfaces," you'll miss out on many great features that are specifically designed to enhance gameplay. The underlying goal of GameplayKit is to create systems that abstract away repetitive details common to gaming development.
Whether you're shuffling a deck of cards or creating a flock of enemy robots hunting down your hero, the framework minimizes overhead and lets you focus more on your unique story. It enables you sidestep recreating common patterns each time you start a project.
Just establish a working model and create the agents that inhabit it. Let GameplayKit handle the details of how those agents achieve their goals. Presets include wandering, fleeing, seeking, flocking (called cohering), following paths, and obstacle avoidance. It's a pretty flexible set.
The following video demonstrates a simple seeker that tracks down a randomly moving target. The agent doesn't just stop and change directions when the target updates. Its velocity vectors must decelerate, rotate, and re-target. It feels much more natural than turning on a dime. GameplayKit handles all of this on your behalf.
Here's what the core code looks like for this demonstration. It's extremely minimal.
let goal = GKGoal(toSeekAgent: targetAgent) let behavior = GKBehavior(goal: goal, weight: 1) myAgent.behavior = behavior
This snippet creates and assigns a seeking behavior that targets another agent. Each time the "hero" agent updates its state, I can test whether the goal has succeeded:
let d = Distance(myAgent.cgPosition, targetAgent.cgPosition)
When the agent has reached its goal, I move the target and reset the behavior. Although this example uses just one behavior, you can assign several behaviors to any agent at a single time. You weight them by priority. A single agent might seek some goal (at, say 60%) while avoiding other agents (at 40%), for example. The higher a goal is weighed, the more it affects the engine's choice of outcomes.
In GameplayKit, you control the clock. You advance it only when and how you see fit. You can tie that clock to a SpriteKit update: method, to an NSTimer, to a CADisplayLink firing, or even run a for-loop iteratively without any real-world analogy to the "time". Agents update directly (myAgent.updateWithDeltaTime(dTime)) or use a coordinator (GKComponentSystem) that synchronously dispatches updates to all its children.
At least in its initial release, GameplayKit classes use simd structs to represent most vector values. I quickly found myself building extension to support conversion between these and more common Core Graphics structs.
public extension CGPoint { var simdValue : float2 { return float2(x.floatValue, y.floatValue) } }
GameplayKit, unsurprisingly, is limited to iOS 9.0-and-later and OS X 10.11 El Capitan-and-later. If you want to explore, you may want to stick to iOS. It’s hard to explore new technologies on OS X unless you’re willing to use a beta IDE with a beta SDK to create beta code in a beta OS. The iPhone allows you to remain in a stable Yosemite environment while tasting the delights of beta API improvements.
You'll probably want to avoid GameplayKit in the Swift playground, at least for a while. While Apple promises stability improvements in upcoming betas, your best bet remains creating standard application projects to explore these framework features.
Make sure you target newer iPhones. iPhone 6 works with GameplayKit. iPhone 5 presents bugs that can crash apps when working with agent behaviors. I lost hours and hours to this issue until I finally realized that I needed to use a "newer" simulator target.
If you're looking to get started, Apple offers an excellent agent "catalog" sample code app on its WWDC 2015 sample code page. GameplayKit is definitely an exciting addition to the iOS and OS X framework family. I personally am hoping to soon explore more of the framework's other features including card shuffling and decision tree management. Despite the bugs and early release, GameplayKit is one of the most exciting developments from this year's WWDC.