Goals
The purpose of this section is to show you how to implement projectiles for your First Person Shooter game.
Objectives
By the end of this section of the tutorial, you'll be able to:
Add Projectiles to Your Game
Implement Shooting
Set Up Projectile Collision and Lifetime
Get Your Projectiles to Interact with the World
Add Crosshairs to Your Viewport
Steps
3.1 - Adding Projectiles to Your Game
3.2 - Implementing Shooting
3.3 - Setting Up Projectile Collision and Lifetime
3.4 - Getting Projectiles to Interact with the World
3.5 - Adding Crosshairs to Your Viewport
3.1 - Adding Projectiles to your Game
Now that you have set up your character, it's time to implement a projectile weapon. You are going to program a simple grenade-like projectile to shoot from the center of the screen and fly until it collides with the world. During this step, you are going to add input and create a new code class for our projectile.
Adding Fire Action Mapping
Click the Edit in the Main menu panel, select Project Settings.
Under the Engine heading on the left side of the Project Settings tab, click Input.
Under the Bindings on the right side, click the (+) sign next to Action Mappings.
Click the arrow to the left of Action Mappings.
Type Fire into the text field that appears.
In the dropdown menu, select Left Mouse Button from the Mouse dropdown list.
Your input settings should now look like the following:
Close the Project Settings menu.
Adding a Projectile Class
Click the Tools in the Main menu panel, select New C++ Class....
The Choose Parent Class window appears. Select Actor as the parent class, and click Next.
Name the new class FPSProjectile, then click Create Class.
Adding a USphere Component
The Visual Studio appears automatically with opened
FPSProjectile.hheader file andFPSProjectile.cppimplementation file, when C++ class will be created.Navigate to the
FPSProjectile.hclass header file.Add the SphereComponent header file:
C++FPSProjectile.h#include "Components/SphereComponent.h"For adding a reference to a
USphereComponentin theFPSProjectileinterface, add following code to theFPSProjectile.hunderpublicaccess specifier:C++FPSProjectile.h// Sphere collision component. UPROPERTY(VisibleDefaultsOnly, Category = Projectile) USphereComponent* CollisionComponent;FPSProjectile.hshould now look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "FPSProjectile.generated.h" UCLASS()Navigate to the
FPSProjectile.cppclass implementation file.Add the following code to the
AFPSProjectileconstructor (afterPrimaryActorTick.bcanEverTick) inFPSProjectile.cpp:C++FPSProjectile.cppif(!RootComponent) { RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("ProjectileSceneComponent")); } if(!CollisionComponent) { // Use a sphere as a simple collision representation. CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent")); // Set the sphere's collision radius.You are making
CollisionComponentaRootComponentsince the simulation will drive it.FPSProjectile.cppshould now look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
Adding a Projectile Movement Component
Navigate to the
FPSProjectile.hclass header file.Add the ProjectileMovementComponent header file.
C++FPSProjectile.h#include "GameFramework/ProjectileMovementComponent.h"Add the following code to
FPSProjectile.h, underpublicaccess specifier:C++FPSProjectile.h// Projectile movement component. UPROPERTY(VisibleAnywhere, Category = Movement) UProjectileMovementComponent* ProjectileMovementComponent;FPSProjectile.hshould now look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "FPSProjectile.generated.h"Navigate to the
FPSProjectile.cppclass implementation file.Add the following lines of code to the
AFPSProjectileconstructor inFPSProjectile.cpp:C++FPSProjectile.cppif(!ProjectileMovementComponent) { // Use this component to drive this projectile's movement. ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent); ProjectileMovementComponent->InitialSpeed = 3000.0f; ProjectileMovementComponent->MaxSpeed = 3000.0f; ProjectileMovementComponent->bRotationFollowsVelocity = true; ProjectileMovementComponent->bShouldBounce = true; ProjectileMovementComponent->Bounciness = 0.3f;FPSProjectile.cppshould now look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; if(!RootComponent)
Setting the Projectile's Initial Velocity
Navigate to the
FPSProjectile.hclass header file.Add the following function declaration in
FPSProjectile.h, underpublicaccess specifier:C++FPSProjectile.h// Function that initializes the projectile's velocity in the shoot direction. void FireInDirection(const FVector& ShootDirection);This function will be responsible for launching the projectile.
FPSProjectile.hshould now look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "FPSProjectile.generated.h"Navigate to the
FPSProjectile.cppclass implementation file.Add the following function definition to
FPSProjectile.cpp:C++FPSProjectile.cpp// Function that initializes the projectile's velocity in the shoot direction. void AFPSProjectile::FireInDirection(const FVector& ShootDirection) { ProjectileMovementComponent->Velocity = ShootDirection * ProjectileMovementComponent->InitialSpeed; }You only needed to supply a launch direction because the projectile's speed is defined by
ProjectileMovementComponent.FPSProjectile.cppshould now look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
Binding the Fire Input Action
Navigate to the Solution Explorer in the Visual Studio and open the
FPSCharacter.hclass header file.Add the following function declaration in
FPSCharacter.h, underpublicaccess specifier:C++FPSCharacter.h// Function that handles firing projectiles. UFUNCTION() void Fire();FPSCharacter.hshould now look like the following:C++FPSCharacter.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "FPSCharacter.generated.h"Navigate to the Solution Explorer in the Visual Studio and open the
FPSCharacter.cppclass implementation file.To bind the
Firefunction, add the following code to theSetupPlayerInputComponentfunction inFPSCharacter.cpp:C++FPSCharacter.cppPlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);Add the following function definition to
FPSCharacter.cpp:C++FPSCharacter.cppvoid AFPSCharacter::Fire() { }FPSCharacter.cppshould now look like the following:C++FPSCharacter.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSCharacter.h" // Sets default values AFPSCharacter::AFPSCharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
Defining the Projectile's Spawn Location
When spawning the
FPSProjectileactor, there are two points to consider when implementing theOnFirefunction, namely:Where to spawn the projectile.
The projectile class (so that
FPSCharacterand its derived Blueprint know what projectile to spawn).
You are going to use a camera-space offset vector to determine the projectile's spawn location. You will make this parameter editable so that you can set and tweak it in your
BP_FPSCharacterBlueprint. Ultimately, you'll be able to calculate an initial location for the projectile based on this data.Navigate to the
FPSCharacter.hclass header file.Add the following code to
FPSCharacter.h, underpublicaccess specifier:C++FPSCharacter.h// Gun muzzle offset from the camera location. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay) FVector MuzzleOffset;EditAnywhereenables you to change the value of the muzzle offset within the Defaults mode of the Blueprint Editor or within the Details tab for any instance of the character. TheBlueprintReadWritespecifier enables you to get and set the value of the muzzle offset within a Blueprint.Add the following code to
FPSCharacter.hunder theprotectedaccess specifier:C++FPSCharacter.hprotected: // Projectile class to spawn. UPROPERTY(EditDefaultsOnly, Category = Projectile) TSubclassOf<class AFPSProjectile> ProjectileClass;EditDefaultsOnlymeans that you will only be able to set the projectile class as a default on the Blueprint, not on each instance of the Blueprint.FPSCharacter.hshould look like the following:C++FPSCharacter.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "FPSCharacter.generated.h"
Compiling and Checking Your Code
It is now time to compile and check your newly implemented projectile code.
Save all of your header and implementation files in Visual Studio.
Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
The purpose of this step is to catch any build errors before moving onto the next step. If you encounter any build errors or warnings outside the scope of this tutorial, refer to and the Unreal Engine API Reference.
3.2 - Implementing Shooting
Learn how to implement shooting for your First Person Shooter character.
Implementing the Fire Function
Navigate to the
FPSCharacter.hclass header file.Add the following line to
FPSCharacter.h.C++FPSCharacter.h#include "FPSProjectile.h"Navigate to the
FPSCharacter.cppclass implementation file.Add the following
Firefunction definition toFPSCharacter.cpp:C++FPSCharacter.cppvoid AFPSCharacter::Fire() { // Attempt to fire a projectile. if (ProjectileClass) { // Get the camera transform. FVector CameraLocation; FRotator CameraRotation; GetActorEyesViewPoint(CameraLocation, CameraRotation);FPSCharacter.hshould now look like the following:C++FPSCharacter.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "FPSProjectile.h" #include "FPSCharacter.generated.h"FPSCharacter.cppshould now look like the following:C++FPSCharacter.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSCharacter.h" // Sets default values AFPSCharacter::AFPSCharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;Save
FPSCharacter.handFPSCharacter.cppin Visual Studio.Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
Importing the Projectile Mesh
Before continuing, download and extract the sample mesh from the following link:
Open Unreal Engine, navigate to the Content Browser and open the Content folder.
Right-click inside the file window of the Content Browser to open the Import Asset dialog window.
Although we cover right-click import, there are three methods to import content. For information about how to import content see Importing Assets Directly:
Click Import to /Game... to open the Import dialog window.
Locate and select the Sphere.fbx mesh file, where you have downloaded this file.
Click Open to begin importing the mesh to your project.
The FBX Import Options dialog window appears. Clicking Import All adds your mesh to the Project.
Click File in the Main menu panel, select Save all to save your imported mesh.
Adding the Projectile's Mesh
Open Visual Studio and navigate to the Solution Explorer.
In the Solution Explorer open the
FPSProjectile.hclass header file.Add the following code to
FPSProjectile.hunder thepublicaccess specifier:C++FPSProjectile.h// Projectile mesh UPROPERTY(VisibleDefaultsOnly, Category = Projectile) UStaticMeshComponent* ProjectileMeshComponent;Navigate to the Solution Explorer in Visual Studio and open the
FPSProjectile.cppclass implementation file.Add the following code to the constructor in
FPSProjectile.cpp:C++FPSProjectile.cppif(!ProjectileMeshComponent) { ProjectileMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileMeshComponent")); static ConstructorHelpers::FObjectFinder<UStaticMesh>Mesh(TEXT("[ADD STATIC MESH ASSET REFERENCE]")); if(Mesh.Succeeded()) { ProjectileMeshComponent->SetStaticMesh(Mesh.Object); } }Open the Unreal Editor. navigate to the Content Browser, right-click the Sphere static mesh and select Copy Reference:
Open Visual Studio, go back to the
ProjectileMeshComponentcode inFPSProjectile.cppand replace[ADD STATIC MESH ASSET REFERENCE]with the copied reference. Your code should look similar to the following:C++FPSProjectile.cppif(!ProjectileMeshComponent) { ProjectileMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileMeshComponent")); static ConstructorHelpers::FObjectFinder<UStaticMesh>Mesh(TEXT("'/Game/Sphere.Sphere'")); if(Mesh.Succeeded()) { ProjectileMeshComponent->SetStaticMesh(Mesh.Object); } }Your asset reference path may vary depending on where you saved the Sphere mesh in the Content Browser. Also, when you paste in the copied asset reference, the reference contains the asset's type name before the asset's reference path. In your case, you will observe StaticMesh'/Game/Sphere.Sphere'. Make sure to remove the asset's type name (for example, StaticMesh) from the reference path.
FPSProjectile.hshould look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "FPSProjectile.generated.h"FPSProjectile.cppshould look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;Save
FPSProjectile.handFPSProjectile.cppin Visual Studio.Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
Adding the Projectile's Material
In Visual Studio navigate to the
FPSProjectile.hand add the following code toFPSProjectile.hunder thepublicaccess specifier:C++FPSProjectile.h// Projectile material UPROPERTY(VisibleDefaultsOnly, Category = Movement) UMaterialInstanceDynamic* ProjectileMaterialInstance;Navigate to the
FPSProjectile.cppand add the following code to the bottom of theif (!ProjectileMeshComponent)constructor:C++FPSProjectile.cppstatic ConstructorHelpers::FObjectFinder<UMaterial>Material(TEXT("[ADD MATERIAL ASSET REFERENCE]")); if (Material.Succeeded()) { ProjectileMaterialInstance = UMaterialInstanceDynamic::Create(Material.Object, ProjectileMeshComponent); } ProjectileMeshComponent->SetMaterial(0, ProjectileMaterialInstance); ProjectileMeshComponent->SetRelativeScale3D(FVector(0.09f, 0.09f, 0.09f)); ProjectileMeshComponent->SetupAttachment(RootComponent);Open Unreal Engine and navigate to the Content folder of the Content Browser. Right-click in the file window of the Content Browser and select Material.
Name the new material SphereMaterial.
Set up the new material's node graph with properties similar to the following:
Base Color: drag off Base Color pin, in the window appears search for and select the Constant3Vector node, set it to (R:1; G:0; B:0)
Specular: drag off Specular pin, in the window appears search for and select the Constant node, set its Value to 0.5
Emissive Color: drag off Emissive Color, in the window appears search for and select the Constant node, set its Value to 0.05
During this step, you are creating a basic Material asset. If you want to learn how to make more complex materials, read how to use and make Materials.
After setting up the new material's node graph, click Save, and navigate to the Content Browser.
Right-click the Sphere material and select Copy Reference.
Go back to the
ProjectileMeshComponentcode inFPSProjectile.cppand replace[ADD MATERIAL ASSET REFERENCE]with the copied reference. Your code should look similar to the following:C++FPSProjectile.cppstatic ConstructorHelpers::FObjectFinder<UMaterial>Material(TEXT("'/Game/SphereMaterial.SphereMaterial'")); if (Material.Succeeded()) { ProjectileMaterialInstance = UMaterialInstanceDynamic::Create(Material.Object, ProjectileMeshComponent); } ProjectileMeshComponent->SetMaterial(0, ProjectileMaterialInstance); ProjectileMeshComponent->SetRelativeScale3D(FVector(0.09f, 0.09f, 0.09f)); ProjectileMeshComponent->SetupAttachment(RootComponent);Your asset reference path may vary depending on where you saved the Sphere material in the Content Browser. Also, when you paste in the copied asset reference, the reference contains the asset's type name before the asset's reference path. In our case, you will observe Material'/Game/Sphere.Sphere'. Make sure to remove the asset's type name (for example, Material) from the reference path.
FPSProjectile.hshould look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "FPSProjectile.generated.h"FPSProjectile.cppshould look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;Open UE, navigate to the Blueprints folder in the Content Browser and open the BP_FPSCharacter file.
Open the Full Blueprint Editor (if necessary), navigate to Components panel and select BP_FPSCharacter (Self) component.
Navigate to the Detail panel in the opened Blueprint Editor.
Find the Projectile section, and in the dropdown next to Projectile Class, select FPSProjectile.
If you can't find the FPSProjectile in the opened dropdown menu, please rerun Unreal Engine.
Click Compile and Save buttons.
Open the Visual Studio, navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
Run the game in PIE mode to verify that the Static Mesh and Material are being spawned in the scene.
3.3 - Setting up Projectile Collision and Lifetime
Currently, our projectiles:
Live forever (they never disappear from the Scene Outliner)
Don't collide with other objects in the world
During this step, you are going to set up projectile collision and lifetime.
Limiting the Projectile's Life Span
Open the Visual Studio and navigate to the Solution Explorer.
In the Solution Explorer open the
FPSProjectile.cppclass implementation file.Add the following code to the
AFPSProjectile::AFPSProjectile()constructor of theFPSProjectile.cppto set the projectile's lifespan:C++FPSProjectile.cpp// Delete the projectile after 3 seconds. InitialLifeSpan = 3.0f;FPSProjectile.cppshould look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;Save your file.
Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
To verify that the projectiles are being destroyed after three seconds, run the game in PIE mode.
As verified in the Outliner, every spawned projectile will disappear from the scene after three seconds.
Editing the Projectile's Collision Settings
Unreal Engine comes packaged with several preset collision channels; however, the Engine also provides customizable channels that game projects can use.
To create a custom collision channel, navigate to Unreal Engine and open Project Settings, select the Engine heading on the left side and select Collision, expand Preset section on the right side.
Navigate to the Object Channels and select New Object Channel... to create a new collision channel. Name your new collision channel Projectile and verify that the Default Response is set to Block before clicking Accept.
Select New... under Preset and name your new profile Projectile. Reference the following image to set your collision presets and click Accept.
This collision profile specifies that the projectile will be blocked by Static Actors, Dynamic Actors, Actors simulating Physics, Vehicles, and Destructible Actors. Also, this collision profile specifies that the projectile overlaps Pawns.
Using the New Collision Channel's Settings
Open the Visual Studio and navigate to the
FPSProjectile.cppclass implementation file.In the
FPSProjectileconstructor, add the following line to theif (!CollisionComponent)block, afterCreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));:C++FPSProjectile.cpp// Set the sphere's collision profile name to "Projectile". CollisionComponent->BodyInstance.SetCollisionProfileName(TEXT("Projectile"));FPSProjectile.cppshould now look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;Save your file.
Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
3.4 - Getting Projectiles to Interact with the World
Now that you can detect the projectile's collision interactions, you can determine how to respond to those collisions. During this step, you will add an OnHit function to FPSProjectile that'll respond to collision events.
Getting Projectiles to React to Collisions
Open
FPSProjectile.h.Add the following code to
FPSProjectile.hunder thepublicaccess specifier:C++FPSProjectile.h// Function that is called when the projectile hits something. UFUNCTION() void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);FPSProjectile.hshould now look like the following:C++FPSProjectile.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "FPSProjectile.generated.h"Open
FPSProjectile.cppto add the following code:C++FPSProjectile.cpp// Function that is called when the projectile hits something. void AFPSProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit) { if (OtherActor != this && OtherComponent->IsSimulatingPhysics()) { OtherComponent->AddImpulseAtLocation(ProjectileMovementComponent->Velocity * 100.0f, Hit.ImpactPoint); } Destroy(); }In the
FPSProjectileconstructor, add the following line to theif (!CollisionComponent)block, afterBodyInstance.SetCollisionProfileName:C++FPSProjectile.cpp// Event called when component hits something. CollisionComponent->OnComponentHit.AddDynamic(this, &AFPSProjectile::OnHit);FPSProjectile.cppshould now look like the following:C++FPSProjectile.cpp// Copyright Epic Games, Inc. All Rights Reserved. #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
Testing Projectile Collision
Save your files in Visual Studio.
Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
After the build finishes, go back to your FPSProject in the Unreal Editor.
Navigate to the Outliner and select the Floor Static Mesh.
Copy and paste selected Floor mesh.
Making sure that the ratio lock is unlocked (the lock icon next to the Scale row), set options of the Transform section in the Detail panel of the Floor2 as following:
Location: (0.0, 0.0, 150);
Rotation: (0.0, 0.0, 0.0);
Scale: (0.2, 0.2, 3.0).
Scroll down to the Physics section and check the Simulate Physics box.
Click the File in the Main menu panel and select Save All to save your imported mesh.
Click the Play button in the Level Editor Toolbar.
To verify that projectiles are colliding with the cube, left-click your mouse button to fire projectiles and move the cube around your level.
Congratulations, your projectiles are complete!Press the Shift + Escape or click Stop in the Level Editor Toolbar to exit PIE mode.
3.5 - Adding Crosshairs to your Viewport
During this step, you will add a crosshair HUD element to our game so that you can aim our projectiles.
Importing a Crosshair Asset
Before getting started, download and extract the sample image from the following link:
Navigate to the Content Browser and open the Content folder.
Right-click inside the file window of the Content Browser to open the Import Asset dialog window.
Click 'Import to / Game...' to open the Import dialog window.
Locate and select the crosshair.TGA image file, where you have downloaded this file.
Click Open to begin importing the image file to your project.
Click the File in the Main menu panel to save your imported mesh.
Adding a New HUD Class
Click the Tools in the Main menu panel, New C++ Class... to choose your new parent class.
The Choose Parent Class menu appears. Select HUD as the parent class and click Next.
Name the new class FPSHUD, then click Create Class.
The Visual Studio appears automatically with opened
FPSHUD.hheader file andFPSHUD.cppimplementation file, when C++ class will be created.Navigate to the
FPSHUD.hclass header file, and add the following variable under theprotectedaccess specifier:C++FPSHUD.hprotected: // This will be drawn at the center of the screen. UPROPERTY(EditDefaultsOnly) UTexture2D* CrosshairTexture;Add the following function declaration in
FPSHUD.hunder thepublicaccess specifier:C++FPSHUD.hpublic: // Primary draw call for the HUD. virtual void DrawHUD() override;Add the following header file to
FPSHUD.h:C++FPSHUD.h#include "Engine/Canvas.h"FPSHUD.hshould now look like the following:C++FPSHUD.h// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/HUD.h" #include "Engine/Canvas.h" #include "FPSHUD.generated.h" /**Open the
FPSHUD.cppimplementation file and add theDrawHUDfunction:C++FPSHUD.cppvoid AFPSHUD::DrawHUD() { Super::DrawHUD(); if (CrosshairTexture) { // Find the center of our canvas. FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f); // Offset by half of the texture's dimensions so that the center of the texture aligns with the center of the Canvas.Save
FPSHUD.handFPSHUD.cppin Visual Studio.Navigate to the Solution Explorer and select FPSProject.
Right-click on FPSProject and select Build to compile your project.
Extending your CPP HUD Class to Blueprints
Now is a good time to extend the CPP HUD class to Blueprints. If you need a refresher, go to our C++ and Blueprints reference page to learn more about extending C++ classes to Blueprints.
Right-click the
FPSHUDclass to open the C++ Class Actions menu.Click Create Blueprint class based on FPSHUD to open the Add Blueprint Class dialog menu.
Name your new Blueprint Class BP_FPSHUD and choose the Blueprints folder before clicking the Create Blueprint Class button.
By now, you should have a newly created BP_FPSHUD Blueprint Class located inside of the Blueprints folder.
Make sure to save your BP_FPSHUD Blueprint before closing the Blueprint Editor.
Setting the Default HUD Class
Click the Edit in the Main menu panel, select Project Settings.
Under the Project heading on the left side of the Project Settings tab, click on Maps & Modes.
Select BP_FPSHUD in the Default HUD dropdown menu.
Close the Project Settings menu.
Go back and open the BP_FPSHUD in the Blueprint Editor.
Now, click on the dropdown menu located in the FPSHUD section of the Blueprint Editor to select your crosshair texture.
Finally, Compile and Save the BP_FPSHUD Blueprint before closing the Blueprint Editor.
Verifying your HUD
Click the Play button in the Level Editor Toolbar. You should now be able to aim the projectiles with your newly added crosshair.
Press the Shift + Escape or click Stop in the Level Editor Toolbar to exit PIE mode.
Finished Section Code
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "FPSProjectile.generated.h"
// Copyright Epic Games, Inc. All Rights Reserved.
#include "FPSProjectile.h"
// Sets default values
AFPSProjectile::AFPSProjectile()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "FPSProjectile.h"
#include "FPSCharacter.generated.h"
// Copyright Epic Games, Inc. All Rights Reserved.
#include "FPSCharacter.h"
// Sets default values
AFPSCharacter::AFPSCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "Engine/Canvas.h"
#include "FPSHUD.generated.h"
/**
// Copyright Epic Games, Inc. All Rights Reserved.
#include "FPSHUD.h"
void AFPSHUD::DrawHUD()
{
Super::DrawHUD();
if (CrosshairTexture)
{
Congratulations! You've learned how to:
✓ Add Projectiles to your Game
✓ Implement Shooting
✓ Set-up Projectile Collision and Lifetime
✓ Get your Projectiles to Interact with the World
✓ Add Crosshairs to your Viewport
You're now ready to learn how to animate your character in the next section.