So far, you’ve used a Post Process Volume to adjust pre-existing settings that control the look of your scene. To add your own custom post-process effect, you can create a post-process material. The material can then apply that effect to the camera or add it to a Post Process Volume to affect what the player sees on screen.
In this part of the series, you’ll add an effect to visually convey damage on screen when the player takes damage. The edges of the screen will pulse in red. As the player’s health gets lower, the effect intensifies and takes up more space on the screen.
To implement this, you’ll:
Build a parent post-process material.
Create a Material Instance to control the parameters in the parent material.
Display and control the on-screen effect with Blueprint Visual Scripting.
Modify the player character’s blueprint logic so their health (HP) regenerates after a period of time, making the damaged-player visual effect disappear.
Before You Begin
Make sure you understand these topics covered in previous sections of the Art Pass for a Puzzle Adventure Game tutorial series:
Building Materials and Material Instances.
Adding a Post Process Volume to a level.
You’ll work with the following assets in the sample project file:
BP_AdventureCharacterBlueprint
Create a Material to Show Damage
First, you’ll make a material that will be the base that defines the effect’s appearance. The material will create a grayscale mask, making the in-game camera view display on the lighter parts of the mask and the pulsing-red damage effect appear on the darker parts of the mask.
To create a new post-process material, follow these steps:
In the Content Browser, go to the AdventureGame > Artist > Materials folder.
In the Materials folder, create a new Material asset named
M_Screen_Damage. Open the material.In the Details panel, change the material Domain to Post Process.
You’ll notice this changes what pins are available on the material’s root node. For a post-process material, you’ll only control the emissive color because these materials don’t use scene lighting.
In Surface-type materials, the emissive color controls how much light the material gives off. When you change a material’s Domain to Post Process, it’s no longer shading a surface, but writing directly to the screen. In this case, emissive color controls the final output color for each pixel.
Define the Damage Effect Shape
Now, you’ll start building the material’s graph, starting with the mask that defines the shape of the post-process effect. First, you’ll use a GeneratedRoundRectNode to draw a grayscale mask in the shape of a rounded rectangle, where the inside of the shape is white and the outside is black. Later, you’ll define what appears on each part of the mask.
To create the grayscale mask, follow these steps:
In the material graph, on the left side of the material root node, add a GeneratedRoundRect node.
You can see an example of the node’s output in the preview window if you connect it to the material root node.
Add a ScreenPosition node.
Connect the ScreenPosition node's ViewportUV output to the UV Coords (V2) input on the GeneratedRoundRect node.
The ViewportUV output tells the GeneratedRoundRect node to draw the mask within the same space as the viewport screen’s coordinates.
To control the mask’s shape with a vector parameter, follow these steps:
Add a Constant4Vector node. You can use this node to create a color value, or use it more broadly as a collection of values that can control the size and shape of the GeneratedRoundRect mask.
Press and hold 4 on your keyboard and click the graph to add this node.
Right-click the vector node and select Convert to Parameter to turn the constant into a Vector Parameter. Name it
Damage Mask Controls.With Vector Parameters, you can use each channel’s value the same as you would separate single-value Constant (or Scalar Parameter) nodes, making your graph more efficient and tidier. By default, the values have RGBA color channel labels, but you can make these values represent whatever you like by renaming them in the node’s Details panel.
In the Details panel, in the Parameter Customization category, expand Channel Names and assign names to each color channel in the vector parameter node. You’ll name these channels to correspond to the GeneratedRoundRect node’s inputs:
R =
Size XG =
Size YB =
Corner RadiusA =
Sharpness
In the Material Expression Vector Parameter category, expand Default Value and set the following default values for each channel:
Size X = 1
Size Y = 1
Corner Radius = 0.4
Sharpness = 0.2
In the graph, drag off the constant vector node’s Size X pin and create an AppendVector node.
Connect the Size Y pin to the Append node’s B input.
Connect the Append node’s output pin to the Box Dimensions pin on the GeneratedRoundRect node.
Connect the Corner Radius and Sharpness pins on the Damage Mask Controls and GeneratedRoundRect nodes.
Add a comment block around these nodes labelled
Damage Mask Falloff.
In the GeneratedRoundRectNode, UV Coords defines where the material draws the rectangle, and Box Dimensions defines how large the rectangle is within that space. Box Dimensions of (1, 1) make the rectangle (or white portion) take up most of the screen space, and (0.5, 0.5) make the rectangle fill half the screen’s width and height.
To view the rectangular mask, follow these steps:
Connect the GeneratedRoundRect node to the Emissive Color input of the material root node.
Select the Damage Mask Controls node and experiment with different Size, Corner Radius, and Sharpness values to see the effect each has on the rectangle.
Reset the values back to the defaults you set earlier, and delete the wire between GeneratedRoundRect and the main material node.
Display Visuals on Different Parts of the Mask
In Expanded Material Instances, you used linear interpolation (lerp) to blend between dry and wet looks on your stone floor material. The floor material’s Lerp node used a Timeline as the Alpha input to blend between two parameter values. Remember, in a Lerp node, the Alpha input controls how much the Lerp blends between A and B inputs. When Alpha is 0, you get all A. When Alpha is 1, you get all B.
The Alpha value can also come from a grayscale mask where each pixel provides a value: white areas show B, black areas show A, and gray areas blend between them. So in this section, you’ll use a Lerp node to blend between your unobscured game view in the middle of the screen (where the mask is white) to a red color along the edge of the screen (where the mask is black).
To blend between the game screen and the red color that represents damage taken, follow these steps:
To the right of the GeneratedRoundRect node, add a LinearInterpolate (or Lerp) node. Hover over the node, click the Toggle Comment Bubble button, and enter
1.Numbering your Lerp nodes helps you follow along with the tutorial since this graph uses several Lerp nodes. We’ll refer to this node as Lerp (1).
Connect the GeneratedRoundRect Result output to the Alpha input of the Lerp (1) node.
Add a SceneTexture node.
In the Details panel, change the Scene Texture Id to PostProcessInput0.
Connect the Color output of the SceneTexture node to the B input of the Lerp (1) node.
In the graph, add a Constant3Vector. Right-click the node and select Convert to Parameter. Name the parameter
Damage Color. This parameter controls the color of the damage effect.Click the color swatch next to Default Value and change the color to red (R = 1).
Connect the Damage Color node’s top (white) pin to the A input on the Lerp (1) node. The top pin of the damage color only outputs the three RGB color channels.
Connect the Lerp (1) output to the material root node’s Emissive Color pin to check the results in the preview window. You’ll see an undefined arithmetic error due to a Float3-to-Float4 conversion issue.
The Damage Color node’s top pin outputs a Float3 value (three channels, RGB), and the SceneTexture node’s Color pin outputs a Float4 value (four channels, RGBA). To resolve this error and make the value types match, you can use a Component Mask to remove the Alpha channel from the Color output of the Scene Texture, since you only need the three channels (RGB) to match. Component Masks are a common way to solve this sort of error.
To turn the SceneTexture node’s color into a Float3 value and resolve the error, follow these steps:
Add a ComponentMask node and connect the SceneTexture node’s Color pin to the Mask node.
Connect the output of the Mask node to the B input of the Lerp (1) node.
Click the arrow at the bottom of the Mask node to see checkboxes for each channel in the Color output.
By default, the component mask only masks R and G channels. Add a checkmark next to B. This creates a Float3 component mask so both Lerp (1) inputs use the same channels.
The graph should look like this:
The material should look like this in your preview viewport:
Add Noise and Variation to the Effect
In this section, you’ll build out the noise section of the material by applying a texture around the outer edge of the frame. With this, you can use material parameters to direct the final look of the effect as it relates to the character’s damage in-game.
In visual effects, noise adds controlled randomness. It’s a pattern you can use to make materials feel more organic and less perfect, like on uneven surfaces or on a flickering light.
To add noise to the material, follow these steps:
At the bottom of the graph, add a ScreenAlignedUVs node. With the ScreenAlignedUVs node, you can map a texture or effect across the entire screen. It generates UV coordinates for the whole viewport or screen.
Drag off the X 100%, Y 100% pin and add a Multiply node.
Right-click and create a Constant node. Right-click it, select Convert to Parameter, and name it Noise Tiling. Connect it to the B input of the Multiply node.
In the Noise Tiling node, set the Default Value to
1.Drag off the Multiply node’s output pin and create a TextureSample node, with the wire connected to the UVs input.
Right-click on TextureSample, convert it to a parameter, and name it
Noise Texture.With the Noise Texture node selected, near the bottom of the Details panel in the Material Expression Texture Base category, set the Noise Texture texture assignment slot to
TilingNoise05.This texture is a part of the Engine Content included with Unreal Engine. You can use your own, but this one is a good default to start with if you don’t have an alternative. Note that if you use a different texture, your results may differ from those shown in this tutorial.
Drag off the R channel of the Noise Texture node and create a Multiply node.
Right-click its B pin and select Promote to Parameter. Name the parameter
Noise Falloffand set its Default Value to1.Drag off the Multiply node’s output pin and create a Power node.
Right-click the Exp pin and select Promote to Parameter. Name the parameter
Noise Amountand set its Default Value to1.Select the eight nodes you just created and press C to add a comment box around them. Label the comment box
Noise in Damage Mask.
At this point, you can test this part of the material by connecting the Power node directly to the Emissive Color input on the M_Screen_Damage material root node. You should see the following in the preview window:
When you’re done testing, disconnect the material root node from the noise texture logic and reconnect it to the Lerp (1) node. You’ll continue to build other parts of the material before connecting everything later in this guide.
Add Noise to the Mask
Now that you have your noise mask, you need to blend it into the damage mask falloff by combining the two using a multiply node. This applies the noise mask to the inner-edge results of the damage mask closest to the center of the screen.
To add the noise texture to the black areas of the mask, follow these steps:
Move the
M_Screen_Damagematerial root node to the right to create some space next to the GeneratedRoundRect node. Delete the wire between the GeneratedRoundRect node and the existing Lerp (1) node since you’ll be adding new logic here.Right-click the graph and create a new Lerp node. Hover over the node, click Toggle Comment Bubble, and enter
2as the comment.Connect the Result pin of the GenerateRoundRect node to the Alpha pin of the Lerp (2) node.
Drag the output of the GenerateRoundRect node and create a One Minus node.
Drag off the One Minus node, create an Add node, and connect its output to the Lerp (2) node’s B pin.
Drag off the One Minus node and add a Multiply node.
Drag off the Multiply output, add a new One Minus node, and connect it to the B input of the Add node.
After the Lerp (2) node, add a Saturate node. This clamps the output values in a 0-1 range.
Add a comment to this logic and label it
Gets the Brightest Spots of the Mask.
At this point, you’re material should look similar to this:
Connect the Noise, Mask, and Damage Color Sections
To connect the Noise, Damage Mask, and Damage Color elements of the graph, follow these steps:
In the Noise Mask logic, drag off the Power node and connect it to the B input of the Multiply node in the Damage Mask Area logic.
Use reroute nodes on any wire to help create clearer paths and reorganize the graph. Double-click on a wire to add a reroute node, then drag it to change the wire’s path.
Connect the Saturate node’s output pin to the Lerp (1) node’s Alpha pin.
Save and Apply changes to the material.
You can connect the Lerp (1) node to the Emissive Color input on the material root node to see the result:
Now, you’ve defined a rectangular mask area, applied a color to this mask, created a noise mask using a texture, and blended them into what you see in the material editor preview window.
Add Pulsations to the Damage Effect
In this section, you’ll build the material logic that causes the red color damage indicator around the edge to pulse as the player takes more damage. You’ll use a Sine node to drive the pulsing behavior, and modify the sine wave to only use positive values.
To make the red effect pulse as the damage increases, follow these steps:
In an empty section at the top of your graph, add a Time node.
The Time node outputs the passage of time in the editor and is helpful for animating materials and changing them over a specified period.
Drag off its pin and add a Multiply node.
Create a Constant node, convert it to a parameter, and name it Pulse Speed. In the node, set its Default Value to
0.5.Connect Pulse Speed to the B input on the Multiply node.
Drag off the Multiply node and add a Sine node.
The Sine node converts the increasing Time value into a value that smoothly oscillates between -1 and 1 in a repeating wave pattern.
Drag off the Sine node output and add an Add node. Ensure its B input value is set to 1.0.
Drag off the Add node and add a Divide node. Ensure its B input is 2.0.
By setting up this Add 1 and Divide by 2, you’re changing the sine wave to go from 1 to 0 instead of between 1 and -1. This prevents the Sine node from inverting the texture’s values, causing it to flash from red to light blue (the inversion of red).
Drag off the Divide node and add a Multiply node.
Drag off its B input and create a Constant. Convert it to a parameter and name it
Pulse Amount. Set its Default Value to1.Select the nodes in this section of the graph and press C to add a comment block. Label it
Damage Pulse Amount and Speed.
Your material now contains all the primary elements that comprise the damage effect for this post-process material. Your graph should look similar to this one now:
Connect the Pulse Logic
Now that you’ve got the pulsing logic set up, you’ll integrate this into the application of damage color to the scene texture. Then, you can change the intensity of the mask as it pulses.
You’ll build off the Damage Pulse Amount and Speed section and add expressions that connect the pulse logic to the Damage Color and Scene Texture sections of the graph.
While working in this section, you’ll be disconnecting some elements you’ve already set up in previous sections and integrating new connections. You can drag nodes around to create space when overlapping wires are difficult to follow.
To connect the pulse logic to the damage color, follow these steps:
Right-click in the graph and create a new Lerp node near the Damage Color node and pulse logic. Label it with a
3.At the end of the pulse logic, connect the output of the Multiply node to the Alpha pin of Lerp (3).
In the Lerp (3) node, the Alpha controls the amount of pulse applied to the mask and how often the pulse should happen.
Delete the Damage Color wire from the A input of Lerp (1), and connect it to the B input of the new Lerp (3) node.
Select the Damage Color node. In the Details panel under Parameter Customization, expand Channel Names, and use the text field to change the A channel name to
Color Amount.In the Material Expressions Vector Parameter category, under Default Value, set the Color Amount value to
2.On the Damage Color node, drag off the Color Amount pin, add a Divide node, and connect its output to the A input of the Lerp (3) node.
Create a new Lerp node near the Lerp (3) node and pulse logic. Label it with a
4.Connect the Lerp (3) node’s output to the Alpha input of Lerp (4).
Connect the RGB (white color) pin of the Damage Color node to the B input of Lerp (4).
Return to the Mask (RGB) node connected to the SceneTexture node. Connect the Mask node’s output to the A input of Lerp (4). The component mask node now has wires going to Lerp (1) input B and Lerp (4) input A.
Connect the output of Lerp (4) to the A input of Lerp (1).
Drag and select the Lerp (3) and Lerp (4) nodes. Press C to create a comment box around them, and label it
Lerp Pulse and Color.Click Save and Apply.
This new part of the graph should look like this:
You can connect Lerp (3) to the Emissive Color input on the material root node to see the results of the damage effect in the material preview window:
In the example above, the Color Amount value on the Damage Color node has been increased to 5.0 to make the effect clearly visible in the preview window.
In the graph, change the Pulse Speed and Pulse Amount values to see how they change the size of the effect and the speed at which the effect is applied. Pulse Amount must be between 0 and 1. In later steps, you’ll be able to control both of these parameters in a Material Instance.
Control the Effect with a Damage Amount Parameter
The last thing you’ll add to your material graph is a new parameter called Damage Amount that controls the effect's size based on how much damage the player has received when playing the game.
This parameter will be set in the character’s Blueprint so that when the player takes damage, the parameter controls the amount of pulsing damage displayed around the outer edges of the screen. The more damage the player takes, the stronger the effect of this material becomes on the player’s screen.
To add a parameter that controls the size of the effect at runtime, follow these steps:
Add some space between your existing material logic and the
M_Screen_Damagematerial root node. Right-click the graph and add a Lerp node. Label this Lerp node with a5.Connect the Mask (RGB) node’s output to the A pin of the Lerp (5) node.
Connect the Lerp (1) node’s output to the B input of Lerp (5).
On Lerp (5), right-click the Alpha pin and select Promote to Parameter, name the parameter Damage Amount, and change its default value to
1.Name this parameter accurately and ensure it has a default value; the player character blueprint will use this parameter to control how much this material appears on screen when the player takes and heals from damage.
Connect the Lerp (5) node’s output to the Emissive Color input of the root node.
The Damage Amount value uses a value between 0 (no damage, effect off) and 1 (max damage, effect on).
This is the result you’ll see in the preview window:
In the example here, the Color Amount value on the Damage Color node has been increased to 5.0 to make the effect clearly visible in the preview window.
Next, you’ll add a new set of nodes that uses Damage Amount as input to affect the size of the GeneratedRoundRect mask. This addition makes the damage effect pulse inward toward the center of the screen as the player takes more damage, and recede as the player’s health is regenerated.
To make Damage Amount affect the size and intensity of the damage mask, follow these steps:
In the material graph, go to the Damage Mask Falloff section. Delete the wire between the Append node and the GeneratedRoundRect node.
Drag off the Append node and add a Multiply node.
Connect the output of the Multiply node to the Box Dimensions input of the GeneratedRoundRect node.
On the Multiply node, drag off input B and add a Lerp node. Label the Lerp node
6.On the Lerp (6) node, leave the A value at 0 and set the B value to
0.75.Right-click the Lerp (6) node’s Alpha and choose Promote to Parameter. Name the node Damage Amount to match your other Damage Amount node. Alternatively, you could copy and paste the original Damage Amount node.
Click Apply and Save.
This is the result you’ll see in the preview window:
In the example here, the Color Amount value on the Damage Color node has been increased to 5.0 to make the effect clearly visible in the preview window.
Your M_Screen_Damage material graph should look like the following when everything is built:
To copy this snippet into your project, delete any existing nodes in your material graph, click Copy Full Snippet, and press Ctrl + V in your material. Then, connect the Lerp (5) node to the main material node’s Emissive Color pin.
Create a Material Instance to Control the Effect
Now that you have your material, create a Material Instance to control all the parameters you created in the material. You’ll use the exposed parameters in the material instance to define the final look and feel of the damage effect on screen.
To set up a Material Instance to control material parameters, follow these steps:
In the Content Browser, in your Artist > Materials folder, right-click the material
M_Screen_Damageand select Create Material Instance from the context menu.Name the asset
MI_Screen_Damageand open it.To make the material preview run in real-time and see how changing parameters affects the material, click the yellow stopwatch button above the viewport twice.
In the Details panel, expand the sections in Parameter Groups to see all the parameters you’ve exposed in the material. Expand the vector parameters, like Damage Mask Controls, to see their individual parameter values.
Add checkmarks next to all parameters except Noise Texture to allow them to be overridden.
Removing the checkmark from a parameter after you’ve changed its value uses the original default value set in the parent material.
While working on your material instance, experiment with the different parameters to see how they affect the damage effect in the preview window. Try different values for Pulse Amount, Noise Falloff, Pulse Speed, and the Damage Mask Controls (vector parameter) to see how these change the effect.
The value for Damage Amount is set to 1 by default, so you can see the changes happening to the material in the preview window. However, change this to
0so that when the game starts, the effect doesn’t appear on screen until the player is damaged. In the next section, you’ll make the player character blueprint control this value.Save the Material Instance.
Later, when you’re able to test the effect in-game, you can return to the Material Instance and repeat these steps to adjust the effect.
Set Parameter Values in the Material Instance
This tutorial’s sample level uses the following parameter values. You can use these values or adjust them as desired in your project.
Parameter | Default Values | Suggested Values |
Global Scalar Parameter Values | ||
Damage Amount | 0 | 0 |
Noise Amount | 1.0 | 0.35 |
Noise Falloff | 1.0 | 0.75 |
Noise Tiling | 1.0 | 1.1 |
Pulse Amount | 1.0 | 0.75 |
Pulse Speed | 0.5 | 0.65 |
Global Texture Parameter Values | ||
Noise Texture | TilingNoise05 | TilingNoise05 |
Global Vector Parameter Values | ||
Damage Color | Hex sRGB: FF0000FF | Hex sRGB: FF0000FF |
Damage Color: Color Amount | 2.0 | 5.0 |
Damage Mask Controls: Size X | 1.0 | 0.75 |
Damage Mask Controls: Size Y | 1.0 | 0.5 |
Damage Mask Controls: Corner Radius | 0.4 | 2.0 |
Damage Mask Controls: Sharpness | 0.2 | 2.1 |
[Optional] Organize and Limit Parameter Values
To make the Material Instance’s parameter values simpler to navigate and use and reduce the chance of extreme values, you can organize parameters in groups and apply value ranges to keep numerical sliders within acceptable or intended values.
For example, Damage Amount is used to mirror the health of the player, where 0 is no damage on screen and 1 is full damage on screen, so it makes sense to set up a slider that is within this range since it can’t exceed that range.
In the parent material, select each named parameter and use the Details panel to set up each one’s Group and Slider Min and Slider Max range as follows:
Parameter | Group | Slider Min | Slider Max |
Damage Amount | Damage | 0 | 1 |
Pulse Amount | Pulse | 0 | 1 |
Pulse Speed | Pulse | 0 | 2 |
Damage Color: Color Amount | Pulse | N/A | N/A |
Noise Tiling | Noise | -1 | 2 |
Noise Falloff | Noise | 1 | 5 |
Noise Amount | Noise | 0.5 | 3 |
Damage Mask Controls | Noise | N/A | N/A |
Noise Texture | Noise | N/A | N/A |
In the Material Instance, you can see how this change affects this value in the parameters list. Parameters are organized into new categories depending on their Group. You can drag sliders between their min and max values without exceeding those values. However, you can override the slider’s limits by manually entering a new value.
Add the Post-Process Material to the Character Blueprint
You now have the post-process material set up and instanced. Next, you’ll set up the character’s blueprint to create and use a Dynamic Material Instance (also called a Material Instance Dynamic, or MID). This will use the MI_Screen_Damage material instance to read the parameter named Damage Amount in the Blueprint. Using logic you set up in the blueprint graph, you can make material adjustments in real-time based on what’s happening during gameplay by injecting a value into the material instance for Damage Amount.
The character has a Health variable that changes when they are damaged. You’ll use this variable with the material instance to apply the effect to the character's screen as they take more damage and remove the effect as their health regenerates.
Create a Dynamic Material Instance and Add it to Post-Processing
Your material instance is an asset that you can’t directly modify at runtime. Instead, in the character blueprint, you’ll create a Dynamic Material Instance. A Dynamic Material Instance is a runtime version of a material instance, created when the game starts, that you can change while the game is running through its named parameters. Then, you’ll assign the MID to the player’s camera so that it’s displayed on screen when the player takes damage.
To create and save an instance of your material in a variable, follow these steps:
In the Content Browser, go to Content > AdventureGame > Designer > Blueprints > Characters and open the
BP_AdventureCharacterblueprint.In the Event Graph, find the group of logic that starts with the Event BeginPlay node. Drag this group to an area of the graph with more space so you can add more nodes to this logic.
To find an event node in the graph, in the My Blueprint panel, expand the EventGraph list, and double-click Event BeginPlay. The graph view focuses on that node.
After the Set Default Movement Speed node, drag off the execution (exec) pin and add a Create Dynamic Material Instance node.
On this Create Dynamic Material Instance node, set the Parent to
MI_ScreenDamage. This is the material instance you created earlier that you’ll use to control the damage effect on the screen.Right-click the node’s Return Value pin and select Promote to Variable.
In the My Blueprint panel, in the Variables list, rename NewVar to
MID Damage.
Now, the Create Dynamic Material Instance node creates a runtime version of MI_Screen_Damage and saves it in the new variable, making it available to reference elsewhere in your graph.
To assign the material instance to the camera’s post-processing pass, follow these steps:
In the Components panel, drag the FirstPersonCamera component onto the graph. This creates a reference to the player camera.
Drag off its output and create a Set Post Process Settings node.
Connect the two Set nodes’ exec pins.
Drag off the Set Post Process Settings node’s Post Process Settings input and add a Make Post Process Settings node.
Select the Make Post Process Settings node. In the Details panel, in the Rendering Features category, add a check mark next to Post Process Materials to add that pin to the Make Post Process Settings node.
In the node, right-click the Post Process Materials input pin and select Split Struct Pin. The pin now takes an array as input.
Drag off the Post Process Materials Array pin and add a Make Array node.
Drag off the Make Array node’s [0] input and add a Make Weighted Blendable node.
On the Make Weighted Blendable node, change Weight to
1.Drag off the Set MID Damage node’s output (blue) pin and connect it to the Make Weighted Blendable node’s Object input.
A Set node’s output pin gives a reference to that variable.
Select the nodes you’ve added in the graph and press C to create a comment box around them. Label it
Create Dynamic Material Instance for Post-Process Effect and assign to Player Camera.Compile and Save the blueprint.
This logic creates the Dynamic Material Instance when the game starts and applies it to the first-person camera of this blueprint.
The new section of the player’s Event BeginPlay logic looks like this:
Here's a snippet of the highlighted section above that you can copy into the event graph instead of building the logic yourself:
Test the Effect In-Game
In the Material Instance (MI_Screen_Damage), temporarily change Damage Amount to 1, and click Save. When you play the game, you can test the effect without taking damage to dial in the look and feel you want for the effect. With Damage Amount set to 1, the material is turned on continuously. When you’re done testing the material, set the Damage Amount back to 0.
Next, you’ll add the logic to the character blueprint that tells this material instance dynamic to appear when the character receives damage and recede when their health regenerates.
Hide or Show the Effect With Damage Taken
To make the Dynamic Material Instance effect only appear when the player is damaged, you’ll extend the existing damage-handling logic in the player character.
This new logic needs to:
Change the material’s Damage Amount parameter based on the character’s Health variable so that:
There is no post-process effect on the screen when Health is full.
There is a post-process effect on the screen that intensifies as Health decreases.
Restore Health to full after the player doesn’t take damage for a period of time, removing the post-process effect.
Create a Maximum Health Variable
You'll be working with the player's health value, so it's best to save the player's maximum health in a variable that you can reference throughout the damage-effect logic instead of entering a static, hard-coded value of 100. This way, if you decide to give your character more or less starting health, your blueprint logic still works properly.
To create a variable that stores the player's maximum health, follow these steps:
In
BP_AdventureCharacter, in the My Blueprint panel, in the Variables section, click + to add a new variable.Name it
MaxHealthand change the type to Float. Compile the blueprint.In the event graph, in the Event BeginPlay group of logic you were working with in the previous section, focus on the Event BeginPlay and Set Default Movement Speed nodes.
Drag off Event BeginPlay and add a Set MaxHealth node.
From the Variables list, drag the Health variable onto the new Set node's Max Health pin.
Now when the game starts, the Health value (100 by default) is saved to MaxHealth. As the player plays the game and Health changes, MaxHealth stays the same, preserving the player's maximum health.
Connect Current Player Health to the Material
First, you’ll extend the player’s damage-handling logic to control the Dynamic Material Instance using the Damage Amount parameter so that as the player’s health decreases, the intensity of the effect on screen increases.
To scale the Damage Amount up as the player loses health, follow these steps:
In the character blueprint, go to the group of logic labelled (DT) Damage and defeat handling near the bottom-left section of the event graph. You’re going to add new logic between the Set Health and the Branch nodes, so add some space between these nodes.
In the Variables list, drag the MID Damage variable onto the graph and select Get MID Damage.
Drag off the Get MID Damage node's output pin and choose Set Scalar Parameter Value from the list.
Connect Set Health to the Set Scalar Parameter Value, and then to the Branch node.
On the Set Scalar Parameter Value node, for the Parameter Name, enter
Damage Amount. This is the material parameter that controls the size and strength of the effect on-screen.This name MUST match the corresponding parameter in the material
M_Screen_Damagefor the effect to work.On the Set Scalar Parameter Value node, drag off the Value input and create a Lerp node.
On the Lerp node, set A to
1.0and B to0. This remaps the values so that when damage is applied, it goes from max health (100) to 0 as you lose health instead of the other way around.On the Lerp node, drag off the Alpha input and create a Divide node.
From the Variables list, drag the character’s Health variable onto the top input of the Divide node.
Drag the character's MaxHealth variable onto the bottom input of the Divide node.
The Divide node turns the player’s health into a number between 1 and 0, where 1 is full health (no damage). However, the Damage Amount value needs to increase as the player loses health, not decrease. The Lerp node reverses the value range. For example, if Health is 25, the Lerp returns a value of 0.75 to the Set Scalar Parameter Value node, resulting in an effect that is 75% of the maximum intensity.
The (DT) Damage and defeat handling section of the graph should look similar to this now:
Add a Resetting Delay to Regenerate Health
For the player’s Health variable (or HP) to regenerate to full so the damage effect disappears, the player character should stop taking damage for a short amount of time. You’ll use a Retriggerable Delay node to implement a five-second delay that must complete before Health is restored. You can use this type of delay node to reset a cooldown — it waits for a set amount of time before executing the next node, but if it’s triggered again before the time runs out, it restarts the countdown.
To add a delay before removing the damage effect, follow these steps:
Under the Branch node, drag off the Fn Set HP node’s exec pin and add a Sequence node. You’ll use this to add a series of actions to execute after the player takes damage and is not yet out of health.
Drag off the Then 0 path and add a Retriggerable Delay node. In the delay node, set the Duration to
5seconds.As a best practice, check that the player is still alive after the delay:
Drag off the Retriggerable Delay and add a Branch node.
On the Branch node, drag off the Condition pin and add a Greater (>) node.
In the Variables panel, drag a Health variable onto the top pin of the Greater (>) node.
Now, each time the player takes damage and isn’t eliminated (their health is not 0), the time delay restarts from 0. Next, you’ll set up the logic that should execute after the delay completes.
Your blueprint graph should look similar to this now:
Set Up a Timeline for Blending Player Health
In this section of the graph, you’ll add a Timeline that you’ll use to gradually regenerate the player’s Health over a short time. The Timeline node’s controls define how it starts, stops, and what happens during the track time.
To set up a five-second-long Timeline, follow these steps:
In the graph under the Sequence node’s Then 0 logic, right-click the graph, search for
add timelinein the node actions list, and select Add Timeline. Name the Timeline nodeDamage Blend.Double-click the Damage Blend node to open it in its own tab in the blueprint.
In this tab, click + Track > Add Float Track to add a new track to the Timeline.
Name the track Blend. This track label also appears as an output pin on the Damage Blend Timeline node.
Next to the + Track button, ensure the Length is 5 seconds.
In the Blend track, right-click and select Add key to CurveFloat_0. Repeat this to add another key; you need two in total.
Click the first key to select it and change its values to Time = 0 and Value = 0.
Click the second key and change its values to Time = 5 and Value = 1.
Right-click the first key and select Auto. This changes the blend from linear blending to a smooth blend between 0 and 1.
Using the blueprint tabs, go back to the Event Graph where the Damage Blend Timeline node is located.
On the Sequence node, connect the Then 1 exec pin to the Damage Blend node’s Stop pin.
From the Branch node after the delay, drag off True and connect it to the Play from Start input on the Damage Blend node.
Now, this Timeline node outputs a value that changes from 0 to 1 over five seconds. When the Retriggerable Delay finishes, the Timeline plays. When the Timeline track logic finishes, execution continues through the Then 1 path and stops the Timeline from updating.
Restore Player Health and Remove the Post-Process Material
Now that you have a Timeline set up, you’ll build the logic that uses the five-second track to blend the player’s Health variable back to its full, starting value and lower the material’s Damage Amount back to 0.
To gradually restore player health using the Timeline, follow these steps:
After the Damage Blend Timeline node, create a Lerp node. Connect the timeline's Blend output pin to the Alpha input on the Lerp node.
On the Lerp node, drag off the B input and add a reference to MaxHealth.
In the Variables list, drag the Health variable onto the A input of the Lerp node.
Drag off the Lerp node’s Return Value pin and add a Set Health node (under Variables > Default in the node actions list).
Drag off the Timeline’s Update pin and connect it to the Set Health node’s exec pin.
Now, the Lerp node blends from the player’s current Health value to the maximum health they had at the start of the game (in this case, 100) over five seconds (the length of the Timeline).
Return to the part of the Event Graph with the Set Scalar Parameter Value node you created before the Branch node. Drag to select the Set Scalar Parameter Value, MID Damage, Lerp, Divide, and Health nodes and press Ctrl+C to copy them.
In the Event Graph, return to the Damage Blend Timeline and press Ctrl+V to paste the nodes.
Connect the Set Health node's exec pin to the Set Scalar Parameter Value exec pin.
Now, as the player’s Health variable is restored to full, Damage Amount decreases back to 0.
Your graph should look similar to this now:
Display Updated Health on the HUD
As the Health variable regenerates back to 100, it displays on the player’s UI with two decimal places. To remove this visual noise from the HUD, you’ll add logic that removes the decimal places and only displays Health as a whole number.
This is an example that shows the difference between using Truncate to remove decimal places:
To ensure player Health is a round number when displayed in the HUD, follow these steps:
Go to the Fn Set HP node that executes before the Sequence node you created. Select the Fn Set HP node and its inputs (HUD and Health) and press Ctrl + C to copy.
After the Set Scalar Parameter Value node at the end of your Timeline logic, press Ctrl + V to paste the three nodes.
Connect the Set Scalar Parameter Value and Fn Set HP nodes’ exec pins.
Drag the Fn Set HP node to the right to create some space.
Delete the wire between the Health variable and the New HP input on the Fn Set HP node.
Drag off the Health variable and add a Truncate node. This converts the float value to an integer, removing any decimal places.
Drag off the Truncate node and connect it to the Fn Set HP node’s New HP input. Unreal Engine automatically adds an Integer-to-Float conversion node.
Compile and Save the blueprint.
Your complete Blueprint should look like this now with all the additions you made:
Test The Final Effect
When you play the game now and take damage, you should see the post-process damage effect appear and grow as you take more damage.
You can return to the Material Instance and adjust the parameter values to achieve the final look you want. The damage effect is amplified in the example below.
Next Up
In the next section, you'll learn to enhance your level's atmospheric elements by adding denser fog in low-lying areas and adding storm clouds in the sky.