Skip to content

Instantly share code, notes, and snippets.

@eka
Created January 30, 2024 14:47
Show Gist options
  • Save eka/a9786ea896de949897b4654f0a8585cf to your computer and use it in GitHub Desktop.
Save eka/a9786ea896de949897b4654f0a8585cf to your computer and use it in GitHub Desktop.
Using Interfaces to implement MagicProjectile hitting something
// Fill out your copyright notice in the Description page of Project Settings.
#include "ExplosiveBarrel.h"
#include "PhysicsEngine/RadialForceComponent.h"
// Sets default values
AExplosiveBarrel::AExplosiveBarrel()
{
// 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;
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>("StaticMeshComp");
StaticMeshComp->SetSimulatePhysics(true);
RootComponent = StaticMeshComp;
RadialForceComp = CreateDefaultSubobject<URadialForceComponent>("RadialForceComp");
RadialForceComp->SetupAttachment(StaticMeshComp);
// Leaving this on applies small constant force via component 'tick' (Optional)
RadialForceComp->SetAutoActivate(false);
RadialForceComp->Radius = 750.0f;
RadialForceComp->ImpulseStrength = 2500.0f; // Alternative: 200000.0 if bImpulseVelChange = false
// Optional, ignores 'Mass' of other objects (if false, the impulse strength will be much higher to push most objects depending on Mass)
RadialForceComp->bImpulseVelChange = true;
// Optional, default constructor of component already adds 4 object types to affect, excluding WorldDynamic
RadialForceComp->AddCollisionChannelToAffect(ECC_WorldDynamic);
}
// Called when the game starts or when spawned
void AExplosiveBarrel::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AExplosiveBarrel::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AExplosiveBarrel::Hit(AActor *HittingActor)
{
UE_LOG(LogTemp, Display, TEXT("ExplosiveBarrel: Got HITT!!"));
RadialForceComp->FireImpulse();
}
// IHitInterface.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "IHitInterface.generated.h"
UINTERFACE(MinimalAPI)
class UHitInterface : public UInterface
{
GENERATED_BODY()
};
class ACTIONROGUELIKE_API IHitInterface
{
GENERATED_BODY()
public:
virtual void Hit(AActor *HittingActor) = 0;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "SMagicProjectile.h"
#include "IHitInterface.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Particles/ParticleSystemComponent.h"
void ASMagicProjectile::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp, Display, TEXT("OnOverlapBegin"));
AActor* PlayerPawn = UGameplayStatics::GetPlayerPawn(this, 0);
// Skip actor
if(PlayerPawn == OtherActor) return;
DrawDebugSphere(
GetWorld(),
GetActorLocation(),
100.0f,
32,
FColor::Red,
false,
1.0f
);
if (IHitInterface* HitActor = Cast<IHitInterface>(OtherActor))
{
HitActor->Hit(this);
}
}
// Sets default values
ASMagicProjectile::ASMagicProjectile()
{
// 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;
SphereComp = CreateDefaultSubobject<USphereComponent>("SphereComp");
SphereComp->SetCollisionProfileName("Projectile");
SphereComp->OnComponentBeginOverlap.AddDynamic(this, &ASMagicProjectile::OnOverlapBegin);
RootComponent = SphereComp;
EffectComp = CreateDefaultSubobject<UParticleSystemComponent>("EffectComp");
EffectComp->SetupAttachment(SphereComp);
MovementComp = CreateDefaultSubobject<UProjectileMovementComponent>("MovementComp");
MovementComp->InitialSpeed = 1000.0f;
MovementComp->bRotationFollowsVelocity = true;
MovementComp->bInitialVelocityInLocalSpace = true;
}
// Called when the game starts or when spawned
void ASMagicProjectile::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ASMagicProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment