In a project involving Blueprint and C++, a common workflow is to create a base class in C++ with variables and functions and then create the child Blueprints that will define the Assets used and that can define other variables and functions specific to the Blueprint.
A base class is also called parent class or superclass.
In this article, we will implement the base class PlayerProjectile in C++. This class represents the projectile fired by the player. In the example project, the player has three types of projectiles that are represented by child Blueprints of PlayerProjectile.
Click on the File menu of the Unreal editor and choose the New C++ Class... option as shown in the image below.
On the next screen, choose the Actor class as the parent class and click the Next button.
In the Name field, write PlayerProjectile. In the Path field, keep the default project folder. Click the Create Class button.
As this is the first C++ class in this Blueprint project, the Unreal editor will convert it to a C++ project.
The PlayerProjectile class will use three components:
- USphereComponent: It is used as the Root component and for collision test.
- UStaticMeshComponent: Contains the Static Mesh that will visually represent the Actor.
- UProjectileMovementComponent: Component used to move the Actor.
Add the declaration of the components in the PlayerProjectile.h file that needs to have this content:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlayerProjectile.generated.h"
UCLASS()
class TUTOPART3_API APlayerProjectile : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APlayerProjectile();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
UStaticMeshComponent* StaticMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
class USphereComponent* CollisionComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
class UProjectileMovementComponent* ProjectileMovement;
};
In the PlayerProjectile.cpp file, we have the initialization of the three components done in the constructor. Don't forget to add the #include lines.
#include "PlayerProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Engine/CollisionProfile.h"
#include "Components/SphereComponent.h"
// Sets default values
APlayerProjectile::APlayerProjectile()
{
PrimaryActorTick.bCanEverTick = true;
InitialLifeSpan = 10.f;
CollisionComponent = CreateDefaultSubobject<USphereComponent>(
TEXT("CollisionComponent"));
RootComponent = CollisionComponent;
CollisionComponent->InitSphereRadius(20.f);
CollisionComponent->SetCollisionProfileName(
UCollisionProfile::BlockAllDynamic_ProfileName);
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetupAttachment(CollisionComponent);
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(
TEXT("ProjectileMovement"));
ProjectileMovement->InitialSpeed = 3000.f;
ProjectileMovement->MaxSpeed = 3000.f;
ProjectileMovement->ProjectileGravityScale = 0.f;
}
// Called when the game starts or when spawned
void APlayerProjectile::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void APlayerProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
Compile the C++ code.
The initial values assigned to the components can be modified in the child Blueprints.
Note that we have not defined the Asset used by Static Mesh. We should avoid referencing folders and Assets directly in C++ code because if an Asset is renamed or moved to another folder, it will cause an error in the C++ code, which will need to be updated and compiled again.
This problem does not happen in Blueprint. The editor automatically updates the references of an Asset in Blueprints when it is renamed or moved to another folder.