Hi All.
I’m seeing different results when I compile and play this section. In the screenshot below, the circles on the arrows represent the origin of the spawns. This is myself and the enemy firing at each other.
Within the BP’s I have double checked that the projectile spawn components are 100 units out in front of the barrels. I have also experimented by moving them around as a test, to no avail. I also went through this video again to see where I strayed, and then also the previous video, in case it was there that I went wrong, but in both cases my code appears the same. Of course I say that, but it is always better to have a second pair of eyes right? Especially since mine are tired!
Can you help? Code below.
ProjectileBase.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProjectileBase.generated.h"
class UProjectileMovementComponent;
UCLASS()
class TOONTANKS_API AProjectileBase : public AActor
{
GENERATED_BODY()
private:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UProjectileMovementComponent* ProjectileMovement;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* ProjectileMesh;
UPROPERTY(EditDefaultsOnly, Category = "Damage")
TSubclassOf<UDamageType> DamageType;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement", meta = (AllowPrivateAccess = "true"))
float MovementSpeed = 1300;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Damage", meta = (AllowPrivateAccess = "true"))
float Damage = 50;
public:
// Sets default values for this actor's properties
AProjectileBase();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
};
ProjectileBase.cpp
#include "ProjectileBase.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
// Sets default values
AProjectileBase::AProjectileBase()
{
// 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;
ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));
RootComponent = ProjectileMesh;
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Projectile Movement"));
ProjectileMovement->InitialSpeed = MovementSpeed;
ProjectileMovement->MaxSpeed = MovementSpeed;
InitialLifeSpan = 3.0f;
}
// Called when the game starts or when spawned
void AProjectileBase::BeginPlay()
{
Super::BeginPlay();
}
PawnBase.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "PawnBase.generated.h"
class UCapsuleComponent;
class AProjectileBase;
UCLASS()
class TOONTANKS_API APawnBase : public APawn
{
GENERATED_BODY()
private:
// COMPONENTS
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UCapsuleComponent* CapsuleComp;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* BaseMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* TurretMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
USceneComponent* ProjectileSpawnPoint;
// VARIABLES
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Projectile Type", meta = (AllowPrivateAccess = "true"))
TSubclassOf<AProjectileBase> ProjectileClass;
public:
// Sets default values for this pawn's properties
APawnBase();
protected:
void RotateTurret(FVector LookAtTarget);
void Fire();
virtual void HandleDestruction();
};
PawnBase.cpp
#include "PawnBase.h"
#include "Components/CapsuleComponent.h"
#include "ToonTanks/Actors/ProjectileBase.h"
// Sets default values
APawnBase::APawnBase()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider")); // first creation of a sub object so capsule will be root
RootComponent = CapsuleComp;
BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Base Mesh"));
BaseMesh->SetupAttachment(RootComponent); // set as child in order to inherit movement
TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TurretMesh"));
TurretMesh->SetupAttachment(BaseMesh);
ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("ProjectileSpawnPoint"));
TurretMesh->SetupAttachment(TurretMesh);
}
void APawnBase::RotateTurret(FVector LookAtTarget)
{
FVector LookAtTargetCleaned = FVector(LookAtTarget.X, LookAtTarget.Y, TurretMesh->GetComponentLocation().Z);
FVector StartLocation = TurretMesh->GetComponentLocation();
FRotator TurretRotation = FVector(LookAtTargetCleaned - StartLocation).Rotation();
TurretMesh->SetWorldRotation(TurretRotation);
}
void APawnBase::Fire()
{
if (ProjectileClass)
{
FVector SpawnLocation = ProjectileSpawnPoint->GetComponentLocation();
FRotator SpawnRotation = ProjectileSpawnPoint->GetComponentRotation();
AProjectileBase* TempProjectile = GetWorld()->SpawnActor<AProjectileBase>(ProjectileClass, SpawnLocation, SpawnRotation);
TempProjectile->SetOwner(this);
}
}
void APawnBase::HandleDestruction()
{
}