Headaches From Out of Date Tutorials

Hello everyone,

Over the last few weeks I have been trying to learn C++ with UE4.8. However there is a distinct lack of really good tutorials for C++ and everyone seems to focus on blueprints. this has lead me to a desperate place of trying my best to hack something together using the engine documentation and my best guess. I’ve tried my best to follow along with the heavily outdated tutorials and I did have some luck when using the 4.X transition guides to convert some of their code. Unfortunately I think I’ve gotten to the point where I’m trying something new and I cant find the resources to help me.

Im trying to build a very simple game with a few mechanics

  1. Sprint
  2. Two types of Pickups
  3. Gather Pickups on collision
  4. Fail state when not enough pickups are gathered in time

I ended up getting the sprint feature to work. However, the compiler tells me that they way I did it will not be compatible with future updates. I tried to work with its suggestions but just ended up breaking everything.

Lets start with HillRunnerCharacter.cpp



//sets BaseSpeed to character default
// This is the line the compiler warns me about and suggests I use GetCharacterMovement() but i cant figure out how to do that.
// as a fairly competent programmer it kills me that i cant access a simple get function
BaseSpeed = CharacterMovement->MaxWalkSpeed;


InputComponent->BindAction("Sprint", IE_Pressed, this, &AHillRunnerCharacter::Sprint);
	InputComponent->BindAction("Sprint", IE_Released, this, &AHillRunnerCharacter::StopSprint);

void AHillRunnerCharacter::Sprint()
{
	CharacterMovement->MaxWalkSpeed *= 2;
}

void AHillRunnerCharacter::StopSprint()
{
	CharacterMovement->MaxWalkSpeed = BaseSpeed;
}


I’m not even sure if the way I’m adding the sprint mechanic is ok but it works and the only sprint tutorials I can find are blueprint based.

Next is the Pickup class. this is the base class for all of my pickups and i wanted to make it as expandable as possible. they way I was thinking this would work is that I extend from this class using one of my other pickups. For example, lets say I was using a battery as a pickup, all i would have to do is setup a function that overrides the base pickup classes Onpickup funtion that gets called on an overlap event. In my mind this would allow me to have many different pickups with very minimal work. Unfortunately, I have a bad feeling I’m wrong about that.

Pickup.H



UCLASS()
class HILLRUNNER_API APickup : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	APickup(const FObjectInitializer& ObjectInitializer);

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pickup")
		bool bIsActive;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Pickup")
		USphereComponent* BaseCollisionComponent;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Pickup")
		UStaticMeshComponent* PickupMesh;

	UPROPERTY(BlueprintAssignable, Category = "Collision")
		FComponentBeginOverlapSignature OnComponentBeginOverlap;

	UFUNCTION()
		void OnPickedUp(AActor* Other);



Pickup.cpp



#include "HillRunner.h"
#include "Pickup.h"


// Sets default values
APickup::APickup(const FObjectInitializer& ObjectInitializer)
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

	PrimaryActorTick.bCanEverTick = false;
	bool bIsActive = false;

	//Create the root SphereComponent to handle the pickup's collision
	BaseCollisionComponent = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("BaseSphereComponent"));

	//Set the SphereComponent as root component
	RootComponent = BaseCollisionComponent;
	//Create the static mesh component 
	PickupMesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("PickupMesh"));
	//Turn physics on for the static mesh 
	PickupMesh->SetSimulatePhysics(true); //Attach StaticMeshComponent to the root component 
	PickupMesh->AttachTo(RootComponent);
	//Calls OnPickedup when an overlap event occurs.
	BaseCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &APickup::OnPickedUp);
}

// Called when the game starts or when spawned
void APickup::BeginPlay()
{
	Super::BeginPlay();
	bIsActive = true;
	
}

//this method will be overridden by different types of Pickups
void APickup::OnPickedUp(AActor* Other)
{

}


BatteryPickup.H



#include "Pickup.h"
#include "BatteryPickup.generated.h"

/**
 * 
 */
UCLASS()
class HILLRUNNER_API ABatteryPickup : public APickup
{
	GENERATED_BODY()

public:
	ABatteryPickup(const FObjectInitializer& ObjectInitializer);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power")
	float PowerLevel;
	
        //When an overlap occurs this function will override the base OnPickup function
	void OnPickedUp(AActor* Other) override; 
};



BatteryPickup.cpp



#include "HillRunner.h"
#include "BatteryPickup.h"


ABatteryPickup::ABatteryPickup(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	PowerLevel = 150;

}

//When an overlap occurs this function will override the base OnPickup function
void ABatteryPickup::OnPickedUp(AActor* Other)
{
	// Call the parent implementation of OnPickedUp first.
	Super::OnPickedUp(Other);

	//Will add code to apply powerlevel to player

	// Destroy the battery
	Destroy();
}


I know this is a lot of help to ask for but any help will be greatly appreciated.

Hi, to use the GetChartacterMovement() function use it like this e.g. in your case
GetCharacterMovement()->MaxWalkSpeed = BaseSpeed;
Hope this helps.

Hmm, I believe that in order to do that AddDynamic thing, you need to have it point to a function that has these arguments;


SomeFunction(AActor* Other, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)

I remember that while following some old tutorials (written when only 3 arguments were required, though my engine version required all 5), there were some problems with my code. I could be wrong though; not exactly an expert myself.

Wow, thank you so much Michael! I’m not sure why but that notation just does not seem intuitive to me.