A node that creates and renders particles.
- iOS 7.0+
- macOS 10.9+
- tvOS 9.0+
- watchOS 3.0+
SKEmitter object is a node that automatically creates and renders small particle sprites. Particles are privately owned by SpriteKit—your game cannot access the generated sprites. For example, this means you cannot add physics shapes to particles. Emitter nodes are often used to create smoke, fire, sparks, and other particle effects. A particle is similar to an
SKSprite object; it renders a textured or untextured image that is sized, colorized, and blended into the scene. However, particles differ from sprites in two important ways:
A particle’s texture is always stretched uniformly.
Particles are not represented by objects in SpriteKit. This means you cannot perform node-related tasks on particles, nor can you associate physics bodies with particles to make them interact with other content. Although there is no visible class representing particles added by the emitter node, you can think of a particle as having properties like any other object.
Particles are purely visual objects, and their behavior is entirely defined by the emitter node that created them. The emitter node contains many properties to control the behavior of the particles it spawns, including:
The birth rate and lifetime the particle. You can also specify the order in which the particles are rendered and the maximum number of particles that are spawned before the emitter turns itself off.
The starting values of the particle, including its position, orientation, color, and size. You can choose to have these starting values randomized.
The changes to apply to the particle over its lifetime. Typically, these are specified as a rate-of-change over time. For example, you might specify that a particle rotates at a particular rate, in radians per second. The emitter automatically updates the particle data each frame. In most cases, you can also create more sophisticated behaviors using keyframe sequences. For example, you might specify a keyframe sequence for a particle so that it starts out small, scales up to a larger size, then shrinks before dying.
Use the Particle Emitter Editor to Experiment with Emitters
In most cases, you never need to configure an emitter node directly in your game. Instead, you use Xcode to configure an emitter node’s properties. As you change the behavior of the emitter node, Xcode immediately provides you an updated visual effect. When complete, Xcode archives the configured emitter. Then, at runtime, your game uses this archive to instantiate a new emitter node.
Using Xcode to create your emitter nodes has a few important advantages:
It is the best way to learn the capabilities of the emitter class.
You can more quickly experiment with new particle effects and see the results immediately.
You separate the task of designing a particle effect from the programming task of using it. Your artists can work on new particle effects independent of your game code.
For more information on using Xcode to create particle effects, see Add a particle emitter to your project.
Listing 1 shows how to load a particle effect that was created by Xcode. All particle effects are saved using Cocoa’s standard archiving mechanisms, so the code first creates a path to the smoke effect, and then loads the archive.
Manually Configuring Particle Creation
SKEmitter class provides many properties for configuring an emitter node’s behavior. The Xcode emitter editor sets the same property values. You can also create and configure your own emitter, or you can take an emitter node created in the Particle Emitter Editor, load it, and change its property values. For example, assume for a moment that you are using the smoke effect in the previous code to show damage to a rocket ship. As the ship takes more damage, you could increase the birth rate of the emitter to add more smoke.
When the emitter node is in a scene, it emits new particles. You use the following properties to define how many particles it creates:
particleproperty specifies the number of particles that the emitter creates every second.
numproperty specifies how many particles are created before the emitter turns itself off. You can also configure the node to emit an unlimited number of particles.
Particles To Emit
When a particle is created, its initial property values are determined by the properties of the emitter. For each of the particle’s properties, the emitter class declares up to four properties:
The average starting value for the property.
A random range for values of the property. Each time a new particle is emitted, a new random value is calculated within that range.
The rate at which the value changes over time, also known as the property’s speed. Not all properties have a speed property.
An optional keyframe sequence.
The complete list of properties used to configure an emitter node is described in
Listing 2 shows how you might configure an emitter’s
scale property. This is a simplified version of a node’s
y properties, and determines how large the particle is.
When a new particle is created, its scale value is a random number from
0. The scale value then decreases at a rate of
0 per second. So, if a particular particle started at the average value,
0, it would decrease from
0 over a period of
Using Keyframe Sequences to Configure Custom Ramps for a Particle Property
SKKeyframe object provides more sophisticated behaviors for a particle property. A keyframe sequence specifies multiple points in a particle’s lifetime and specifies the value for a property at each point. The keyframe sequence then interpolates values between those points and uses them to simulate the particle’s property value.
You can use keyframe sequences to implement many custom behaviors, including:
Changing a property value until it reaches a specific value.
Using multiple different property values over the lifetime of a particle. For example, you might increase the value of the property in one part of the sequence and decrease it in another. Or, when specifying colors, you might specify multiple colors that the particle cycles through during its lifetime.
Changing a property value using a nonlinear curve or a stepping function.
Listing 3 shows how you might replace the code in
SKEmitter to use a sequence. When you use a sequence, the values are not randomized. Instead, the sequence specifies all of the values of the property. Each keyframe value includes a value object and a timestamp. The timestamps are specified in a range from
0 represents the birth of the particle and
1 represents its death. So, for this sequence, the particle starts out with a scale of
0 and increases to
0 one quarter of the way through the sequence. Three quarters of the way through the sequence, it reaches its minimum size,
0. It remains at this size until it dies.
Adding Actions to Particles
Although you do not have direct access to the particles created by SpriteKit, you can specify an action that all particles execute. Whenever a new particle is created, the emitter tells the particle to run that action. You can use actions to create very sophisticated behaviors.
For the purpose of using actions on particles, you can treat the particle as if it were a sprite. This means you can perform other interesting tricks, such as animating the particle’s textures.
Using Target Nodes to Change the Destination of Particles
When the emitter creates particles, they are rendered as children of the emitter node. This means that they inherit the characteristics of the emitter node, just like nodes do. For example, if you rotate the emitter node, the positions of all of the spawned particles are rotated also. Depending on what effect you are simulating with the emitter, this may not be the correct behavior. For example, assume that you are using the emitter node to create the exhaust from a rocket. When the engines are at full burn, a cone of flame should come out the back of the ship. This is easily simulated using particles. But if the particles are rendered relative to the ship, when the ship turns, the exhaust is going to rotate as well. That doesn’t look right. What you really want is for the particles to be spawned, but thereafter be independent of the emitter node. When the emitter node is rotated, new particles get the new orientation, and old particles maintain their old orientation. You make particles independent of the emitter by specifying a target node.
Listing 4 shows how to configure a rocket exhaust effect to use a target node. When the custom sprite node class instantiates the exhaust node, it makes the node its child. However, it redirects the particles to the scene.
When an emitter has a target node, it calculates the position, velocity, and orientation of the particle, exactly as if it were a child of the sprite node. This means that if the ship sprite is rotated, the exhaust orientation is automatically rotated also. However, at the moment a new particle’s starting values are calculated, the values are transformed into the target node’s coordinate system. Thereafter, they would only be affected by changes to the target node.
Particle Emitter Tips
Particle emitters in SpriteKit are one of the most powerful tools for building visual effects. However, used incorrectly, particle emitters can be a bottleneck in the design and implementation of your app. Consider the following tips:
Use Xcode to create and test your particle effects, then load the archives in your game.
Adjust emitter properties sparingly inside your game code. Typically, you do this to specify properties that cannot be specified in the Xcode inspector or to control properties inside your game logic.
Particles are cheaper than a sprite node, but they still have overhead! Try to keep the number of particles onscreen to a minimum by creating particle emitters with a low birth rate, and specifying a short lifetime for particles. For example, instead of creating hundreds or thousands of particles per second, reduce the birth rate and increase the size of the particles slightly. Often, you can create effects with fewer particles but the same net visual appearance.
Use actions on particles only when there isn’t another solution. Executing actions on individual particles is potentially very expensive, especially if the particle emitter also has a high birth rate.
Assign a target node whenever the particles should be independent of the emitter node after they are spawned. For examples, particles should be independent if the emitter node moves or rotates in the scene.
Consider removing a particle emitter from the scene when it is not visible onscreen. Add it just before it becomes visible.