I’ve been attempting to learn C++ over blueprints because I’ve known C++ for a while now and my peers have suggested it over blueprints. Currently, I have a parent class BaseGun which has some basic assignment properties for when I need more than one type of weapon. I also have a child class Rifle which is meant to be the first instance of a weapon in the game.
Using some constructors I am trying to assign some basic values for use later as well as the UStaticMeshComponent. After some research it appeared ConstructorHelpers::FObjectFinder was the best option however despite loading the directory to the static mesh I have it doesn’t load in the editor. I can assign the static mesh just fine in the editor, but I want to have it in the constructor of the class in case I need to make multiple instances of the gun.
I think you need to add “/Game/” to your paths. So it would be “/Game/GroundUp/Content…” for you. But FWIW, I used to do this but now I just Use a UStaticMeshComponent* UPROPERTY in my C++ classes and just set the meshes or anything dynamic in via a corresponding blueprint. Ie If i were you
I would have a BP_Rifle blueprint which has the rifle modle set in it via the editor. I find that this is more flexible and easier to work with.
Yeah, I suggest what @bluffdog mentions as well. It’s best to not hardcode asset paths in C++ code and instead setup a child BP class to assign/tweak visuals.
I attempted to use the blueprint method of assigning the properties as you suggested and the FPS C++ example shows, however I’ve encountered a few issues.
In my cpp file for my BaseGun I attempted to create the default subobject and attach it to the RootComponent however this proved to crash my engine after every start as it said it already existed. I already tried to not attach it to the RootComponent and only use CreateDefaultSubobject but this didn’t remove the error.
I left only the header declaration for the variable hoping it would still be assignable, however when I derived a blueprint class from the C++ class Rifle I could see it had a mesh component however shows up in the BP as a variable but does not allow me to edit it.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BaseGun.generated.h"
//class UStaticMeshComponent;
UCLASS()
class GROUNDUP_API ABaseGun : public AActor
{
GENERATED_BODY()
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
UStaticMeshComponent* GunMesh;
public:
// Sets default values for this actor's properties
ABaseGun();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
void SetMBD(float value);
float GetMBD();
void SetDmg(float value);
float GetDmg();
void SetFR(float value);
float GetFR();
private:
float MaxBulletDistance;
float Damage;
float FireRate;
UStaticMeshComponent* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("GunMesh"));
};
BaseGun.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "BaseGun.h"
// Sets default values
ABaseGun::ABaseGun()
{
// 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;
}
// Called when the game starts or when spawned
void ABaseGun::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ABaseGun::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ABaseGun::SetMBD(float value) {
MaxBulletDistance = value;
}
float ABaseGun::GetMBD() {
return MaxBulletDistance;
}
void ABaseGun::SetDmg(float value) {
Damage = value;
}
float ABaseGun::GetDmg() {
return Damage;
}
void ABaseGun::SetFR(float value) {
FireRate = value;
}
float ABaseGun::GetFR() {
return FireRate;
}
Rifle.h and Rifle.cpp have no code bodies at the moment
Were you able to compile this project with BaseGun.h and BaseGun.cpp as they are? In the header file you commented-out the forward declaration of UStaticMeshComponent. You need to forward declare it. In the cpp file you didn’t include the header file for UStaticMeshComponent, which is
You should be calling CreateDefaultSubobject from the constructor, not within the header file (I’m surprised if that even compiles). For example, your header should have:
public:
UPROPERTY(EditAnywhere)
class UStaticMeshComponent* MeshComponent;
ARifle::ARifle()
{
//TEXT("RifleMesh") is the display name in the editor.
RifleMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RifleMesh"));
//TEXT("StaticMesh'/Game/Geometry/Meshes/1M_Cube.1M_Cube'") reference can be obtained by right click the object you wanted, and click "Copy Reference"
RifleMeshComponent->SetStaticMesh(ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Game/Geometry/Meshes/1M_Cube.1M_Cube'")).Object);
}
To use ConstructorHelpers, remember to include UObject/ConstructorHelpers.h.
To make the static mesh component editable in blueprint, add UPROPERTY().
BaseGun::SetMC(UStaticMeshComponent) was an archaic method I designed to attempt to assign the mesh for its children classes. It has since been deleted as my most recent reply implies.
Do I really have to create a UStaticMeshComponent for each class? My original intention was to have UStaticMeshComponent be created in BaseGun, inherited by the children of that class and then assigned in their respective code/blueprint.
Once I get home I will try and implement the fix with the header file @Marius557 said and the location of the declaration @LivelyGeek said. Didn’t realize I commented the header out.
I could have sworn it compiled this morning however it didn’t when I got home so maybe I’m mistaken.
@LivelyGeek worked like a charm. Called it from the Rifle.cpp though considering my implementation. @Marius557 included it in BaseGun.h instead of the BaseGun.cpp and it worked perfect just like you said (obviously because BaseGun.cpp includes BaseGun.h)