Introduction to Particle Effects
If you’ve ever poked around in our DataBase View, you may have seen the old particle effects are stored there. You can drag them into your level, trigger them, create and edit them directly in the DataBase View. These were our first generation particle effects, and while you can continue to use them, this tutorial series will focus on our second generation Particle Editor.
This first tutorial will explain the main concepts of particle creation. Once we understand those, we’ll be on our way to making all sorts of increasingly complex effects throughout the rest of this series.
Introduction to the Particle Editor
While you can create a new particle asset by right-clicking in the Asset Browser and adding a new particle entity to any folder you like, as explained here, what we recommend is opening the Particle Editor first and creating your first particle from its tool-specific Asset Browser. You can organize your particle assets into any folders within your assets folder. We're going to put ours in a particles folder and name it tutorial_part_1.
Once you have your particle created, you can just drag it from the Particle Editor’s Asset Browser into your level. That creates an instance of the particle effect as an entity with one component, the Particle Emitter. Alternatively you can create a particle component, which you’ll find in the Effects entity components group, but you’ll then need to actually assign a particle effect to it by clicking on the Effect property. The result is the same, but simply dragging is much faster.
For now, the only thing we care about in the Properties panel is that the particle emitter is enabled so we can see how it looks. We’ll look at these properties in depth later. If the enabled property is on, your particle will spawn the moment the level loads, which is appropriate for global effects like snow or a continuously running waterfall, but for effects that should be triggered by player-driven game states or events, the enabled property should be left unchecked and triggered at the appropriate moment through code or visual scripting. Any time you want to test a disabled effect in the Sandbox, you can toggle this property on temporarily.
The Default Sprite
Once you drag your particle into the level, you’ll immediately see this little rectangle which we call a sprite. Move it up so it's free from spawning under the terrain.
The default sprite
This is the default sprite, a simple 2D plane that can have color and movement, emit light, respond to physics and much more. However, unless it’s very simple and very small, we usually replace this default plane with a 2D image - either a simple image or 2D animated image sequences, like bugs flapping their wings, curling smoke, flames, etc. We’ve provided quite a few of these 3D simulations in the assets/particles folder to get you started.
If you click on the particle in the Particle Editor’s Asset Browser, you’ll see exactly how it’s built in the Effect Graph. The Render:Sprites feature is what’s responsible for generating the rectangle which is our current particle. Sprites are just one type of entity you can spawn in a particle, but this is the one you’ll probably use more than any other.
Particle Effect component with the Effect Graph and property Inspector
The box you see in the Effect Graph is called a component, and each of the colorfully named elements in our current component (Spawn:Rate, Life:Time, etc.) is called a feature. As you’ll see, particles can get very, very complicated, with many components, features and modifiers to dynamically trigger components and change values during the life of the particle.
If you rotate the camera around this sprite (Alt-middle mouse drag), you’ll notice that by default, the rectangle always faces the screen. While you can change this behavior, the point of it is to help a 2D image appear to be 3D simply by hiding the fact that it has no volume or thickness. That is the essence of how particles work.
If you click on the Render:Sprites feature, you’ll see its properties in the Inspector panel. The Facing Mode property is what determines how this 2D plane is displayed. The default is to always face the screen, but if we set it to Free mode, we see it for what it really is: just a 2D plane. Whether you want the sprite to face the screen, the camera, or to face the direction in which it's moving depends on the particle design. We’ll explore these other facing modes in more complex use cases. For now, set this to always face the screen.
Like the Material Editor, the Audio Controls Editor and other tools, you have to save your particle entity while the Particle Editor tool is active. Throughout the Sandbox interface, when you have unsaved changes to an entity in a tool like the Particle Editor, you’ll see an asterisk (*) on its icon and name to alert you that you haven’t saved it yet. You can use File → Save in the Particle Editor menu or just Ctrl + S for a quick save, but remember that particles and the open level are saved separately. Saving a particle doesn't save the level, and saving the level (when a viewport is the active tool panel) does not save a particle or other entities that have their own editors.
The Particle Editor Interface
If you click on a component’s title bar or any of its features, you’ll see its properties in the Inspector panel. If you click on a specific feature, you’ll just see its properties in the Inspector, or if you click on the component’s title bar, you’ll see the properties for the component itself and every one of its current features in a long list, which is a convenient way to see the whole component design at once.
The fourth panel is the Curve Editor, which you use to modify how properties change over time or relative to other parameters, much like the curve tool in the Environment Editor.
For more information, you can check out our Particle Editor documentation.
Creating a Smoke Effect
The Field:Size feature sets the size of the sprite. The default value of one produces a two by two meter rectangle because size correlates to the sprite's radius (to the edge of the sprite, not to a vertex).
Spawn:Rate and Life:Time
Next, we need to control when our sprite appears by spawning it. Spawn:Rate is a useful method when you want sprites to appear in a continuous stream at a rate you set. Right now, a new sprite is being spawned once every second, but because the old one never disappears, you can’t actually see that new ones are appearing.
However, if you drag the effect around with the move tool, you’ll notice that it lags, almost as if it keeps getting stuck on something. But it’s actually because a new sprite is in fact being spawned only once per second, and because we haven’t explicitly set up the sprite to follow the movement of the entity component.
To make this spawning and disappearing visible, let's modify how long the sprite lasts through its Life:Time property. Set it to 0.5, and now we finally start to see something a bit more interesting, which is a new sprite appearing every second and disappearing half a second later.
A sprite with Spawn:Rate and Life:Time
A key concept is the difference between Life:Time, which is how long each sprite stays onscreen, and Duration as you see it in the Spawn feature, which is how long the particle continues spawning sprites. Either can be infinite, which is the default, or a finite period of time. You'll also note that even if you delete a particle asset from the level, it plays out to the end of its Life:Time setting; it doesn't necessarily disappear immediately.
There are many ways to add movement to our sprite; the Motion:Physics feature that is already in our component is a good way to begin. Lengthen the Life:Time to three seconds, and let’s start by having gravity affect our sprite. Assuming you haven’t disabled global gravity, the Engine is already calculating acceleration on any physicalized entities from the standard force of gravity, so if you set Gravity Scale to 1 (i.e., 100%), our sprites fall to the terrain as if they had weight. Drag the particle entity up a bit higher above the terrain so you can see them cascading down and disappearing over their three second lifetime.
Gravity Scale = 1
Although this looks very simple, we’ve already created the basis of effects like waterfalls, sparks, or leaves falling to the ground.
If we make Gravity Scale a negative number, we can create things like smoke, where the particles are lighter than air and float up.
Gravity Scale = -1
Let's set our Gravity Scale to -.5 to make our particle float more gently upward.
Replacing the Default Sprite with a Bitmap Image
Our sprite is still just an ordinary rectangle. Let’s change that by adding an entirely new feature by right-clicking on any of these features and inserting a new one. You’ll note that you can insert it before or after where you clicked, although you can always drag features to change their order. And because these are executed top to bottom, we will examine use cases where feature order is going to make a difference.
For now, let’s add an Appearance:Material feature. Click on the textures browser, and since our sprites are already floating upward, let’s create a puff of smoke by browsing to the textures/sprites/smoke folder and choosing smoke_a. This is just a simple bitmap image generated by a simulation program.
Although it still needs work, now we finally have something that you might regard as a more self-respecting and realistic particle.
Gravity = -0.5
Now that we have the basis of a smoke effect, let’s add a few enhancements.
Modifying Size Dynamically
Right now, the smoke stays the same size throughout its life. Let’s make it start small and gradually expand like real smoke. We need to modify the Field:Size over the age of the particle. So if we click on the Field:Size feature, you’ll see a little dropdown menu and the number zero next to the Value box. This allows us to add what we call modifiers that can affect the sprite size in this case. Since we effectively want to plot the size of the particle from small to large over time, we're going to use a curve.
First we're going to make sure that the Curve Editor panel is visible, so when we click on the Curve parameter, we see our very flat curve.
A couple of things to notice: the vertical axis is labeled with simple values, with 1 in the middle. 1 means 100% of whatever Field:Size we’ve set in the first place. Points that we place along the curve can modify the size over the horizontal axis. By default, that’s Age, the entire onscreen appearance of the particle.
Since we want the smoke to grow steadily from nothing, we're going to drag the start point down to 0 and the end point up to 2, or 200%. You can use the scroll wheel to zoom out on the graph and drag these points to any value you prefer.
Changing the particle size dynamically with the Curve Editor
You’ll also notice that the horizontal axis has no labels or specific values at all. That’s because it’s always normalized. It’s not a specific period of time; it’s dynamically linked to Life:Time. It’s called Age to distinguish it from Life:Time, which is an exact duration in seconds. Age is always a dynamic, abstract representation of the entire lifetime of the particle. If we change the Life:Time feature of the particle, the curve is normalized, meaning that these points automatically redistribute themselves along the full length of the horizontal axis. It simply represents Life:Time in a non-numerical way.
Randomizing Particle Size
So now the smoke grows a bit more realistically, but each puff of smoke looks exactly the same. Let's randomize the size. Click and insert another modifier for the size, Random. We can randomize up to 2, or 200% of the original size. Drag the starting size up a bit to about 20-40% rather than starting from nothing. You can also experiment with making Life:Time a bit longer and adjusting Spawn:Rate to control how frequently new puffs of smoke appear.
Making the Smoke Appear and Disappear Smoothly
The smoke also appears and disappears instantly. Let’s use the same curve technique to fade opacity in and out: right-click and add an Appearance:Opacity feature. Right now the opacity is 1 or 100%. Click on the dropdown button to the right of the Value field and select Curve → Age.
Adding Curve → Age to a feature
Click on the Curve parameter to open it in the Curve Editor. (You may need to make the Curve Editor panel visible first.) We want a quick fade in at the beginning and a slow fade out. Double-click on the curve to add a point about 10% of the way into the timeline and another point about 30% from the start. Leave those at 1 (i.e., 100% opacity) and drag the start and end points down to 0.
It's often useful to keep features organized together by category; the color coded labels make this easy. However, since features are executed top to bottom, there will be some cases where features need to be ordered for execution reasons.
You’ll notice that as with other spline-based points, we have handles to control the curvature around each point. If you click on a specific point, you can use the toolbar above the grid to set the incoming and outgoing handles as curves or straight incoming or outgoing lines, and more. Since it doesn’t do us any good to set opacity greater than 100%, you can click on the third point (at 30% on the horizontal axis) and then on the button highlighted in the image below to straighten the incoming curve.
Set in tangent to linear
Now our puff of smoke fades in quickly and fades out gradually, and has some randomization in its size. We’ve made a lot of changes, so let's just press Ctrl + S to save the edits to the particle.
Using an Animated Sprite Sheet
You can continue to improve this by using curves and random modifiers to vary the size and speed of the sprite. But there’s one major weakness: we just have a single static image of smoke. We need what’s commonly known as a sprite sheet, a grid of images that contains an animated image sequence.
So we're going to go back to the Appearance:Material feature, delete the static texture we were using, and browse for a material. Select materials/particles/smoke/smoke_plume_b_9x9.mtl. Even if your thumbnail is missing, the filename alerts you that this is a 9x9 sprite sheet - a good filename strategy - which is why we literally see a grid of nine by nine images spawning as a single image.
To tell the Particle Editor to treat it as a tiled (multi-image) sprite sheet and just show one tile at a time, we need to add an Appearance:TextureTiling feature. Since this is a nine by nine image grid, we're going to set TilesX and Y to 9. We also need to specify the total number of sprites in Tile Count and to specify the same value in the Animation → Frame Count property.
To help avoid mathematical errors or speed up difficult calculations, you can type mathematical operations in any value field and press Enter to let the Engine calculate the result for you. For example, typing 9*9 produces the result 81. You can do this anywhere in the Sandbox Editor.
We're also going to tell the animation to loop repeatedly in the Cycle Mode (this may not be necessary, depending on the Life:Time of the particle), and enable Frame Blending to keep this looking smooth. (Frame Blending crossfades from one frame into the next.)
Adding Random 2D Rotation
The animated image is a big improvement over the single static image. However, the same animation is spawning over and over; we’re only randomizing the size. Let’s add some random rotation. We can use Angles:Rotate2D; we don’t need 3D rotation in this case. Random Angle will set the maximum randomization in degrees as each sprite spawns. And if you want the particle to spin over the course of its lifetime, you can add Random Spin. The example below uses 180° for both of these fields. Note that you will see a higher degree of randomization than is evident in this two second loop.
Modifying Sprite Color
Lastly, let's make our smoke a more consistent dark color: add a Field:Color feature. You can choose any color you like, but for our purpose, just choose a neutral grey close to black. You shouldn’t be surprised to see that you can also add modifiers to this feature just like anything else. For example, you could add a Color Random modifier to vary colors up to 100% through the RGB parameter (which affects hue, saturation, and luminance), and/or add random variations in Luminance.
Final particle so far
Additional Motion:Physics Techniques
In addition to gravity, Motion:Physics provides other ways of moving particles using wind and uniform acceleration. But before we can talk about these options, we need to understand a key concept in particle design.
Since CRYENGINE simulates Earth conditions, it models Earth’s gravity and atmosphere - and the air resistance of physical entities moving through it. In the Particle Editor, that air resistance is called Drag.
It’s air resistance that prevents an object falling to Earth from endlessly accelerating until it lands. When it comes to particles, this drag value determines how quickly particles are affected by air resistance. And with respect to particles in the engine, that can either be air that isn’t moving or wind. In either case, enabling drag means that eventually the particle is going to end up moving at the same speed as the air, whether it’s a hurricane gale or perfectly motionless.
In the image below, the ruler is marked in centimeters. The yellow line is a particle sprite that's being launched using a Velocity:Directional feature, which allows the particle to be launched into motion at a precise starting velocity, in this case one meter per second on the X axis.
Drag = 1, Velocity = 1
Motion:Physics → Drag is set at 1 to demonstrate that a particle initially moving at one meter per second with a Drag of 1 will come to a stop after exactly one meter of travel. If Velocity is doubled to meters per second, drag will stop the particle after two meters of travel. 5 meters per second stops after 5 meters of travel, etc.
Reducing Drag to a lower value means that it takes air resistance a lot longer to bring the particle to a stop.
Drag = 0.5, Velocity = 1
To reiterate: Drag enables air resistance for particles. In this case, drag eventually stops the particles from moving - or more precisely, air resistance eventually "drags" the velocity of the particle until its speed is the same as the motionless air that the engine is modeling.
Affecting Particle Movement with Uniform Wind
But what if the air is moving?
In this next example, we've disabled Velocity:Directional so the particle is initially motionless. Motion:Physics → Drag has been set to zero, and the X value of Uniform Wind has been set to 1 meter per second. Effectively, this creates a local wind volume that just affects the particle. However, the particle won’t move at all without Drag enabled because it has no air resistance.
Drag = 0
If we set Drag to 1, the particle is spawned without any velocity, and immediately the one meter per second wind starts pushing it to accelerate until it matches the wind speed. That acceleration will be complete after one meter of travel distance. This acceleration is easier to see if you set the wind to move a bit faster, as, in the example below. You can see the particle accelerating quickly until it’s moving at the speed of the wind.
Particle moving at the speed of the wind, Drag = 1
Another way to say this is that drag has caused the particle to "stop" moving - relative to the wind flow. That’s what drag does - it stops the movement of a particle relative to the air movement, or lack of it.
Affecting Particles with Global Wind
We can also use the global wind as set in the currently loaded environment preset's Constants → Wind to affect the particle. In the image below, we've set Uniform Wind to 0 and set Level Wind Scale to 1. At a Level Wind Scale of one, the global wind affects particles 100%, so with a drag value of one, the particles will reach the same speed as the global wind after one meter of travel.
When we launched our particle with an initial velocity of one meter per second, Drag stopped the particle; it made the particle's speed the same as the motionless air. With wind, it also “stops” the particle relative to the air, but this time, that air is moving. Ultimately, it’s doing the same thing; all we’re changing is the speed of the wind that’s pushing the particle.
Of course, you can combine these forces: in the example below, we 're using Velocity:Directional to launch the particle to the left with an initial velocity of 10 meters per second, a Drag of 1, and Level Wind Scale set to -2. So in this case, Drag decelerates the particle from its initial velocity of 10 meters per second until it comes to a momentary stop, then accelerates to the right until it reaches one meter per second in the opposite direction (i.e., the speed of the global wind). Note that Level Wind Scale can be set to any positive value; it just acts as a multiplier for the global wind speed.
Drag = 1, Velocity = 10, Level Wind Scale = -2
Effect of Breezes on Particles
If you have random breezes enabled in your environment preset, they will also affect particles that have Drag and Level Wind Scale enabled. If you reveal physics proxies, you can see the breezes represented as red boxes and watch them suddenly accelerating the particles that they touch. Note that in this screenshot, some of the red breeze proxies you see are floating above the particles, thus not affecting them.
Particles and random breezes
One important implication of using enabling Level Wind Scale is that anything that produces wind is going to push every particle that has Drag and Level Wind Scale enabled. That includes other particles that produce a physical force.
In the example below, a first generation explosion effect with Advanced → Force Generation → Wind enabled to the left of the particle is being triggered. The particles are being moved to the left by Level Wind Scale, but the force of the explosion generates a strong temporary wind that pushes the particles rapidly to the right because they have Drag and Level Wind Scale enabled.
Particles and a temporary wind generated by an explosion
Using these settings is a great way to keep particles behaving realistically in response to anything that affects the global wind. Just keep in mind that if you make changes to your environment preset’s wind or breezes settings, every single instance of particles with Level Wind Scale and Drag enabled will be affected.
Lastly, Motion:Physics allows you to provide gravity-like acceleration, but in any direction using the Uniform Acceleration parameters on X, Y, and Z. Increasing Drag will limit the maximum speed this force can achieve. This example sends particles quickly up and to the left with Uniform Acceleration of 50,0,50 and no Drag.
There are many, many ways to introduce movement into a particle. Motion:Physics provides just some of those possibilities.
There are lots of other improvements that we need to make to get this smoke effect to look convincingly realistic, but they have more to do with studying how real smoke behaves in specific situations rather than particle editor features that are unfamiliar at this point. We covered many of the core concepts in this first tutorial in the series, which we’ll expand on as we build more and more complex particle effects in the tutorials that follow.
On This Page
- No labels