GameplayKit Tutorial: Entity-Component System, Agents, Goals, and Behaviors
In this GameplayKit tutorial, you will learn how to create flexible and scalable games by using the Entity-Component system with Agents, Goals and Behaviors. By Ryan Ackermann.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
GameplayKit Tutorial: Entity-Component System, Agents, Goals, and Behaviors
35 mins
Update 03/17/17: This tutorial has been updated for Xcode 8.2.1 and Swift 3. Original tutorial by Ray Wenderlich.
Update 03/17/17: This tutorial has been updated for Xcode 8.2.1 and Swift 3. Original tutorial by Ray Wenderlich.
GameplayKit is an awesome framework introduced in iOS 9 that makes implementing many common tasks in your game much easier.
GameplayKit is a collection of tools that can help you with features like pathfinding, randomization, state machines, rule systems, and more.
In this GameplayKit tutorial, you’re going to focus on two parts of GameplayKit: its Entity-Component system, and Agents, Goals, and Behaviors.
These parts of GameplayKit help you organize your code in a different way that allows for more clean organization and code reuse, especially as your games become larger and more complex.
Let’s dive in!
Getting Started
In this GameplayKit tutorial, you will be working on a simple game called MonsterWars. Download the starter project, open it in Xcode, and build and run to check it out. You’ll see something like the following:
Right now, this game is just a shell with the UI elements added, but no gameplay. Here’s how the game will work:
- You’ll get money every so often, which you can see in the upper left. You can use it to buy units by tapping the buttons at the bottom.
- There are three enemy types: Quirk (fast and cheap), Zap (ranged attackers), and Munch (slow but has AOE chomp).
- If your units destroy the enemy’s castle, you win!
Take a look at the code to see what’s there. Once you feel comfortable, read on to learn more about the main subject of this GameplayKit tutorial: its Entity-Component system.
What is an Entity-Component System?
Quite simply, an entity-component system is an architectural approach that enables your games to grow in size and complexity without increasing the interdependencies in your code.
This works by having 2 types of modular pieces:
- Entities: An entity is a representation of an object in your game. The player, an enemy or a castle are good examples of entities. Since an entity is basically an object, you make this object perform interesting actions by applying components to it.
- Components: A component contains the logic that performs a specific job on one entity, such as modifying its appearance or shooting a rocket. You make small components for each type of action your entities can do. For example, you might make a movement component, a health component, a melee attack component, and so on.
One of the best benefits of this system is that you can reuse components on as many entities as you want, allowing you to keep your code clean and organized.
Your First Component
To get started, let’s create a component to represent a sprite on the screen. In GameplayKit you create components by subclassing GKComponent
.
To do this, select your MonsterWars group in the project navigator, right-click, select New Group, and name the group Components.
Then right-click the Components group, select New File.., select the iOS/Source/Swift File template, and click Next. Name the new file SpriteComponent and click Create.
At this point, your project navigator should look like this:
Open SpriteComponent.swift and replace the contents with the following:
// 1
import SpriteKit
import GameplayKit
// 2
class SpriteComponent: GKComponent {
// 3
let node: SKSpriteNode
// 4
init(texture: SKTexture) {
node = SKSpriteNode(texture: texture, color: .white, size: texture.size())
super.init()
}
// 5
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
In this code you:
- Imported SpriteKit along with GameplayKit so you could access these frameworks.
- Created a component class named
SpriteComponent
by subclassingGKComponent
. - Declared a property named
node
to hold the sprite on this component. - Implemented a basic initializer that creates a sprite node from a texture passed in and assigns it to the
node
property. - Added this required method to achieve compliance with the
GKComponent
class. For now, don’t worry about the fact that it’s not being implemented.
Your First Entity
In GameplayKit, GKEntity
is the class that represents an entity. You make entities do stuff by adding components to it, like the one you just created.
It’s often helpful to create a subclass of GKEntity
for each type of object that you add to the game. In this game for example, there are five types of objects: castles, quirk monsters, zap monsters, munch monsters, and lasers.
Your GKEntity subclass should be very simple. Usually it’s just an initializer that adds the components you need for that type of object.
Let’s create an entity for the castles. To do this, right-click the MonsterWars group in the project navigator, click New Group and name the group Entities.
Then right-click the Entities group, select New File.., select the iOS/Source/Swift File template, and click Next. Name the new file Castle and click Create.
At this point, your project navigator should look like this:
Open Castle.swift and replace the contents with the following:
import SpriteKit
import GameplayKit
// 1
class Castle: GKEntity {
init(imageName: String) {
super.init()
// 2
let spriteComponent = SpriteComponent(texture: SKTexture(imageNamed: imageName))
addComponent(spriteComponent)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
There are just two things to point out here:
- As I mentioned earlier, it’s often convenient to subclass
GKEntity
for each type of object in your game. The alternative is to create a baseGKEntity
and dynamically add the types of components you need; but often you want to have a “cookie cutter” for a particular type of object. That is what this is! - At this point, you add just one component to the entity – the sprite component you created earlier.
Now that you’ve created a component and an entity, you’re almost ready to add it into the game.