Unreal
투사체를 발사하는 기본 몬스터 - 투사체 충돌처리
Yannoo
2025. 1. 16. 01:54
728x90
// Fill out your copyright notice in the Description page of Project Settings.
#include "Weapon/Projectile/SolaProjectileBase.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "GameFramework/Character.h"
#include "GameFramework/DamageType.h"
#include "Engine/Classes/Engine/DamageEvents.h"
ASolaProjectileBase::ASolaProjectileBase()
{
PrimaryActorTick.bCanEverTick = true;
CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComponent"));
CollisionComponent->InitSphereRadius(50.0f);
CollisionComponent->SetCollisionProfileName(TEXT("OverlapAll"));
RootComponent = CollisionComponent;
// OnHit 대신 Overlap 이벤트 바인딩
CollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ASolaProjectileBase::OnOverlapBegin);
//CollisionComponent->OnComponentHit.AddDynamic(this, &ASolaProjectileBase::OnHit);
ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileMesh"));
ProjectileMesh->SetupAttachment(CollisionComponent);
ProjectileMesh->SetVisibility(true); //인게임에서 안보여서 추가
ProjectileMesh->SetHiddenInGame(false);
Movement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovement"));
Movement->InitialSpeed = 1000.0f;
Movement->MaxSpeed = 1000.0f;
Movement->ProjectileGravityScale = 0;
Movement->bRotationFollowsVelocity = true;
Movement->bShouldBounce = false;
// 기본 콜리전 설정
CollisionComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
CollisionComponent->SetCollisionObjectType(ECC_GameTraceChannel1); // Projectile 채널
CollisionComponent->SetCollisionResponseToAllChannels(ECR_Overlap); // 모든 채널에 대해 오버랩
// 프로젝타일 메시는 콜리전 비활성화
ProjectileMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
void ASolaProjectileBase::BeginPlay()
{
Super::BeginPlay();
}
void ASolaProjectileBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASolaProjectileBase::Fire(const FVector& ShootDirection, float lifeSpan)
{
SetLifeSpan(lifeSpan);
UE_LOG(LogTemp, Log, TEXT("%f, %f, %f"), ShootDirection.X, ShootDirection.Y, ShootDirection.Z);
Movement->Velocity = ShootDirection * Movement->InitialSpeed;
}
void ASolaProjectileBase::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
Destroy();
}
void ASolaProjectileBase::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
if (OtherActor)
{
FDamageEvent DamageEvent;
OtherActor->TakeDamage(ProjectileDamage, DamageEvent, GetInstigatorController(), this);
}
// 발사체 제거
Destroy();
}
이 기본 projectile 클래스를 가지고 MonsterProjectile을 구현했다.
#include "MonsterProjectile.h"
#include "GameFramework/Character.h"
#include "Components/SphereComponent.h"
#include "Engine/DamageEvents.h"
AMonsterProjectile::AMonsterProjectile()
{
}
// MonsterProjectile.cpp
void AMonsterProjectile::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (!OtherActor) return;
// 발사한 몬스터 자신은 무시
if (OtherActor == GetOwner())
{
return;
}
// 다른 몬스터들도 무시
if (OtherActor->ActorHasTag("Monster"))
{
return;
}
// 플레이어와 충돌했을 경우
if (OtherActor->ActorHasTag("Player"))
{
FDamageEvent DamageEvent;
OtherActor->TakeDamage(ProjectileDamage, DamageEvent, GetInstigatorController(), this);
UE_LOG(LogTemp, Warning, TEXT("Monster Projectile Hit Player"));
Destroy();
return;
}
// 그 외의 경우 기본 동작 수행 (파괴)
Super::OnOverlapBegin(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult);
}
단순하게 몬스터는 통과하고 플레이어는 TakeDamage 호출,
나머지에 닿는다면 파괴된다.
하지만 지금 동작은 특정 벽에 닿으면 그대로 정지,
플레이어는 통과한다.
collision 채널 설정과 관련있는걸까?
일단 플레이어의 pawn 콜라이더는 worldStatic과의 충돌 방식이 블록이다.
투사체의 collision component는 worldStatic이고 pawn과의 충돌 방식이 오버랩이다.
이 경우 언리얼은 더 허용적인 방식으로 반응 - 즉 오버랩 이벤트가 발생한다고 한다...
콜리전 프리셋이 worldStaticMesh였어서
Projectile이라는 오브젝트 타입을 따로 만들었다. 콜리전 반응에서 바꿀건 없어보이지만 일단 만들었다.
투사체의 Hit 이벤트 발생이 꺼져있었어서 벽과의 충돌이 발생하지 않았던 것 같다. 설정을 바꾸니
이 뒤의 벽과 Hit 충돌은 잘 일어나는데, 플레이와 overlap은 발생하지 않는다. overlap이벤트 발생도 체크해두었는데... 왜일까?
콜리전 프리셋 세팅은 일단 문제가 없다는 것을 확인했다. 그 다음으로는 뭘 확인해야하지?
일단 온힛이 플레이어에게도 똑같이 잘 처리되는지 확인을 해보자.
onHit 은 의도대로 발생하고 데미지 처리도 잘 들어간다.
일단 이렇게 문제를 봉합해두자.....
728x90