Crash probably due to timers

I have never once seen a UE4 project build from Visual Studio while the editor is up. The “hot reload” feature never works right. And I usually get errors whenever I try to compile from within the editor. I always close the editor, build in VS, and relaunch the editor.

But at any rate, if you want to get to the bottom of this, we need more info (i.e. log files).

Hello,

I’m trying to make a base weapon class that contains a bunch of functions that every weapon could use.
Anyway, in it, I’m using timers to control the rate of fire, reload etc.

When I open UE4 for the first time and shoot everything works fine. When I want to change something in the code and then recompile everything, then go back into ue4 and start shooting the editor crashes. Sometimes the editor even crashes after recompiling. After restarting the editor everything works fine again.

The .CPP file:

// Fill out your copyright notice in the Description page of Project Settings.

#include "BaseWeaponClass.h"
#include "Engine/World.h"
#include "Components/SphereComponent.h"

// Sets default values
ABaseWeaponClass::ABaseWeaponClass()
{
 	// 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;

	WeaponMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Weapon Mesh"));
	WeaponMesh->SetOnlyOwnerSee(true);
	WeaponMesh->bCastDynamicShadow = false;
	WeaponMesh->CastShadow = false;
	WeaponMesh->SetupAttachment(RootComponent);

	FireRate	 = 0.075f;
	FireDelay    = FireRate;
	ReloadTime	 = 3.f;
	MagazineSize = 30;
	MagazineAmmo = 30;
	SpareAmmo	 = 100;
	Burst	     = 0;

}

//	Called when the game starts or when spawned
void ABaseWeaponClass::BeginPlay()
{
	Super::BeginPlay();

	//WeaponMesh->SetSkeletalMesh(Model);
}

//	Called every frame
void ABaseWeaponClass::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

//	Resets the firing sequence
void ABaseWeaponClass::Reset()
{
	GetWorldTimerManager().ClearTimer(FiringTimerHandle);
	BurstAmt = 0;
	IsFiring = false;
}

//	Begins the firing sequence
void ABaseWeaponClass::BeginFire()
{
	if (MagazineAmmo > 0 && !IsReloading)
	{
		if (BurstAmt == 0 && CanFire)
		{
			OnFire();
			IsFiring = true;
		}

		if (FireRate > 0)
			FireTimer();

		if (FireDelay > 0)
		{
			CanFire = false;

			DelayTimer();
		}
	}
	else if (MagazineAmmo == 0 && !IsReloading) {
		OnEmpty();
	}
	else if (MagazineAmmo == -1) {
		OnFire();
		IsFiring = true;
	}
}

//	Stops the firing sequence
void ABaseWeaponClass::StopFire()
{
	if (Burst == 0)
	{
		Reset();
	}
}

void ABaseWeaponClass::StartReload()
{
	if (MagazineAmmo < MagazineSize && SpareAmmo > 0) {
		ReloadTimer();

		IsReloading = true;

		if (GEngine)
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Reloading..."));
	}
}

//	Prevents the user from firing faster than the firing rate 
void ABaseWeaponClass::ResetFire()
{
	OnFire();
	CanFire = true;
}

void ABaseWeaponClass::FireTimer()
{
	GetWorldTimerManager().SetTimer(FiringTimerHandle, this, &ABaseWeaponClass::OnFire, FireRate, true);
}

void ABaseWeaponClass::ReloadTimer()
{
	GetWorldTimerManager().SetTimer(ReloadTimerHandle, this, &ABaseWeaponClass::OnReloaded, ReloadTime, false);
}

void ABaseWeaponClass::DelayTimer()
{
	GetWorldTimerManager().SetTimer(SingleFireTimerHandle, this, &ABaseWeaponClass::ResetFire, FireDelay, false);
}

//	Called every time the gun fires
void ABaseWeaponClass::OnFire()
{
	if (MagazineAmmo > 0) {
		MagazineAmmo--;

		BurstAmt++;

		if (GEngine)
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Ammo: " + FString::FromInt(MagazineAmmo) + " BurstAmt: " + FString::FromInt(BurstAmt)));
	}
	else if (MagazineAmmo == 0) {
		OnEmpty();
		Reset();
	}

	// Resets the firing sequence if BurstAmt reaches Burst
	if (GetWorld() && BurstAmt >= Burst && Burst > 0)
	{
		Reset();
	}

}

//	Called when the use fires, but there's no ammo
void ABaseWeaponClass::OnEmpty()
{
	if (GEngine)
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Empty!"));
}

void ABaseWeaponClass::OnReloaded()
{
	int ammoChange = MagazineSize - MagazineAmmo;

	MagazineAmmo += ammoChange;
	SpareAmmo -= ammoChange;

	IsReloading = false;

	if (GEngine)
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Reloaded!"));
}

Here’s the header:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BaseWeaponClass.generated.h"

UCLASS()
class EXIMOD_API ABaseWeaponClass : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ABaseWeaponClass();

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Model")
	class USkeletalMesh* Model;

	// How fast the weapon fires
	UPROPERTY(EditAnywhere, Category = "Settings")
		float FireRate;

	// How fast can the weapon fire again
	UPROPERTY(EditAnywhere, Category = "Settings")
		float FireDelay;

	// How fast can you reload
	UPROPERTY(EditAnywhere, Category = "Settings")
		float ReloadTime;

	// How many bullets are in a magazine
	UPROPERTY(EditAnywhere, Category = "Settings")
		int MagazineSize;

	// How many bullets are left in the magazine
	UPROPERTY(EditAnywhere, Category = "Settings")
		int MagazineAmmo;

	// How many spare bullets are left
	UPROPERTY(EditAnywhere, Category = "Settings")
		int SpareAmmo;

	// How long the weapons bursts (0 = full auto, 1 = semi auto, 3 = 3-round burst etc)
	UPROPERTY(EditAnywhere, Category = "Settings")
		int Burst;

protected:

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

	// Called every time the gun fires
	virtual void OnFire();

	// Called when the gun fires and there's no round in the chamber
	virtual void OnEmpty();

	// Called when the main looping timer needs to be stopped, and when certain variables need to be reset
	virtual void Reset();

	// Called when the gun has finished reloading
	virtual void OnReloaded();

	void ResetFire();

	void FireTimer();
	void ReloadTimer();
	void DelayTimer();


	// The actual mesh in the world
	class USkeletalMeshComponent* WeaponMesh;

	FTimerHandle FiringTimerHandle;
	FTimerHandle SingleFireTimerHandle;
	FTimerHandle ReloadTimerHandle;

	bool CanFire;
	bool IsFiring;
	bool IsReloading;

	int BurstAmt;
public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Call this function to fire the gun
	virtual void BeginFire();

	// Call this function to stop the gun from firing
	virtual void StopFire();

	// Called when the gun starts to reload
	virtual void StartReload();

};

Please bare in mind that this is the first time I’m ever using C++. Other than that I’ve got quite some experience in other languages if that matters.

Any advice on how I could give these log files? Should I copy and paste whatever comes up in VS when I’m compiling?

The bar on the top of the text-entry when you’re posting – there is a way to link to stuff, paste code, and such. The best way is to not paste in a ton of text so we have to scroll the main page, it should be embedded. As far as where to find the logs, that’s something you can learn from a web search.
But it sounds like it’s compiling ok so you want to give us the Editor crash log.