출처: https://handhp1.tistory.com/3 [망고 먹는 개발자:티스토리]
축이 3개로 나눠져 있는 3D 상태에서 회전 하다가 2개축이 겹쳐지는 현상 이것을 징벌락
이라고 부른다
CEnemy.h
public:
FRotator rot;
CEnemy.cpp
#include "Kismet\KismetMathLibrary.h"
void ACEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 해당 방향으로 이동하고 싶다
// 등속운동, 등가속운동
// P = P0 + vt
FVector P0 = GetActorLocation();
FVector vt = dir * speed * DeltaTime;
FVector P = P0 + vt;
SetActorLocation(P);
//추가 XZ를 고정시키면서 징벌락 현상을 방지한다
rot = UKismetMathLibrary::MakeRotFromXZ(GetActorForwardVector(), dir);
//rot = UKismetMathLibrary::FindLookAtRotation(P, P + dir);
SetActorRotation(rot);
}
nullptr 체크 외에도 pending kill 상태인지, garbage 인지 체크한다. 실제로 언리얼의 공식 독스를 보면
Return true if the object is usable
: non-null and not pending kill or garbage
라고 되어 있는걸 볼 수 있습니다. 결국 nullptr인지 pending kill인지 garbage인지, 총 3가지를 체크하는 것입니다.
적 스폰을 위해 C++ 클래스를 하나 제작
CEnemyGOD.h
public:
// 필요속성 : 생성시간 경과시간 적공자
UPROPERTY(EditAnywhere)
float creatTime = 2.0f;
float currentTime = 0;
UPROPERTY(EditDefaultsOnly, Category = "Settings")
TSubclassOf<class ACEnemy> enemyFatory;
UFUNCTION()
void CreateEnemy();
CEnemyGOD.cpp
#include "CEnemy.h"
void ACEnemyGOD::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
CreateEnemy();
}
// 일정시간에 한번씩 적을 만들고 싶다
void ACEnemyGOD::CreateEnemy()
{
// 일정시간에 한번씩 적을 만들고 싶다
// 1. 시간이 흘렀으니까
currentTime += GetWorld()->GetDeltaSeconds();
// 2. 생성 시간이 됐으니까
// -> 만약 경과시간이 생성시간을 초과했다면
if (currentTime >= creatTime)
{
// 3. 적을 만들고 싶다
GetWorld()->SpawnActor<ACEnemy>(enemyFatory, GetActorLocation(), FRotator::ZeroRotator);
// 4. 경과 시간 초기화
currentTime = 0;
}
}
CEnemy.cpp
void ACEnemy::BeginPlay()
{
Super::BeginPlay();
target = Cast<ACPlayer>(UGameplayStatics::GetActorOfClass(GetWorld(), ACPlayer::StaticClass()));
// 태어날때 한번 방향을 정하고 그대로 움직인다
// 30% 확률
int32 ran_num = FMath::RandRange(1, 3);
if (ran_num == 1 && IsValid(target))
{
// Target - enemy = p0까지의 반향
dir = target->GetActorLocation() - GetActorLocation();
dir.Normalize(); // Nomalize
}
else
{
dir = FVector::DownVector;
}
}
Collision 처리를 하지않아 Enemy끼리 부딪히면 부숴지는 현상이 발생한다 이제 Enemy끼리는 부딪혀도 파괴되지않게 하는 방법을 알아보자
코드로 하는 방법
Enemy.cpp
void ACEnemy::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// 방법 1
// 설계도 같은거 쓰고 있니?
auto enemy = Cast<ACEnemy>(OtherActor);
if (enemy)
{
return;
}
// 방법 2
// 부딪힌 녀석이 같은 이름에 Enemy가 포함되어 있니?
/*
if (OtherActor->GetName().Contains("Enemy"))
{
return;
}
*/
// -> 아무 처리하지 않는다
OtherActor->Destroy();
Destroy();
}