프로젝트 세팅 → 엔진 → 콜리전에서 각 채널에 대해서 설정할 수 있다.
오브젝트 채널 및 트레이스 채널을 생성하고, Preset에서 충돌관계를 설정할 수 있다. 새 채널을 설정하면, preset에 있는 기본설정들에는 block으로 설정되기 때문에 필요한 경우 바꾸어 주어야 한다.
콜리전 프리셋을 설정하면, 적용할 캐릭터의 블루프린트에서 Capsule Component → 콜리전 → 콜리전 프리셋 에서 설정한다. 코드로 설정하는 방법도 가능하다.
private:
UFUNCTION()
void AnimNotify_AttackHit();
public:
FOnAttackHit OnAttackHit;
AnimInstance 헤더에 AttackHit 함수와 OnAttackHit라는 변수를 추가했다.
FOnAttackHit 는 델리게이트이다.
void UMyAnimInstance::AnimNotify_AttackHit()
{
//UE_LOG(LogTemp, Log, TEXT("AnimNotify_AttackHit"));
OnAttackHit.Broadcast();
}
AnimInstance cpp파일에 AttackHit함수를 정의헀고, 여기에서 OnAttackHit 함수를 Boradcast 즉 범위에 포함되는 오브젝트들에게 호출신호를 보낸다.
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void PostInitializeComponents() override;
public:
/ ... /
void Attack();
void AttackCheck(); // 함수 선언
Character의 헤더인데 PostInitializeComponents는 Life Cycle 함수 중 BeginPlay보다 먼저 호출되는 함수이다.
Life Cycle 함수는 언리얼에서 선언해놓았으므로 virtual 및 override해서 클래스에 선언한다.
// MyCharacter.cpp
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
void AMyCharacter::PostInitializeComponents()
{
Super::PostInitializeComponents();
AnimInstance = Cast<UMyAnimInstance>(GetMesh()->GetAnimInstance());
if (AnimInstance)
{
AnimInstance->OnMontageEnded.AddDynamic(this, &AMyCharacter::OnAttackMontageEnded);
AnimInstance->OnAttackHit.AddUObject(this, &AMyCharacter::AttackCheck);
}
}
/ ... /
void AMyCharacter::AttackCheck()
{
FHitResult HitResult;
FCollisionQueryParams Params(NAME_None, false, this);
float AttackRange = 100.f;
float AttackRadius = 50.f;
// 채널에 해당하는 충돌이 일어나면 true반환
bool bResult = GetWorld()->SweepSingleByChannel(
OUT HitResult,
GetActorLocation(),
GetActorLocation() + GetActorForwardVector() * AttackRange,
FQuat::Identity,
ECollisionChannel::ECC_GameTraceChannel2, //
FCollisionShape::MakeSphere(AttackRadius),
Params);
// 충돌하고, Actor 값이 있는 경우
if (bResult && HitResult.Actor.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("Hit Actor : %s"), *HitResult.Actor->GetName());
}
}
Character cpp파일에서는 BeginPlay에 있던 AnimInstance를 가져와 대입하는 과정을 PostInitializeComponent로 옮겼다.
AttackCheck에서는 SweepSingleByChannel을 이용해서 충돌체크를 한다.
ECollisionChannel에는 충돌처리 채널을 지정해주어야하는데,
프로젝트 경로 → Config → DefaultEngine.ini 를 참고하면 충돌관련 설정을 한 채널을 확인할 수 있다.
FCollisionShape를 통해 충돌하는 범위의 모양을 설정할 수 있다.
// MyCharacter.cpp
void AMyCharacter::AttackCheck()
{
FHitResult HitResult;
FCollisionQueryParams Params(NAME_None, false, this);
float AttackRange = 100.f;
float AttackRadius = 50.f;
bool bResult = GetWorld()->SweepSingleByChannel(
OUT HitResult,
GetActorLocation(),
GetActorLocation() + GetActorForwardVector() * AttackRange,
FQuat::Identity,
ECollisionChannel::ECC_GameTraceChannel2,
FCollisionShape::MakeSphere(AttackRadius),
Params);
FVector Vec = GetActorForwardVector() * AttackRange; // 방향벡터
FVector Center = GetActorLocation() + Vec * 0.5f; // 중심
float HalfHeight = AttackRange * 0.5f + AttackRadius; // 캡슐 몸통길이
FQuat Rotation = FRotationMatrix::MakeFromZ(Vec).ToQuat(); // rotation
FColor DrawColor; // 색
// 충돌 여부에 따라 색 변화
if (bResult)
DrawColor = FColor::Green;
else
DrawColor = FColor::Red;
// debug 캡슐 그리기
DrawDebugCapsule(GetWorld(), Center, HalfHeight, AttackRadius,
Rotation, DrawColor, false, 2.f);
if (bResult && HitResult.Actor.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("Hit Actor : %s"), *HitResult.Actor->GetName());
}
}
위와같은 방법으로 충돌에 반응하여 캡슐을 그릴 수 있다.
'개발 · 컴퓨터공학' 카테고리의 다른 글
Learning Unreal 4 언리얼 공부일지 - 충돌을 이용한 아이템 습득 (0) | 2022.01.29 |
---|---|
Learning Unreal 4 언리얼 공부일지 - 언리얼의 소켓 (0) | 2022.01.28 |
Learning Unreal 4 언리얼 공부일지 - 블렌드 스페이스가 뭐지 (0) | 2022.01.26 |
Learning Unreal 4 언리얼 공부일지 - 애니메이션 노티파이 (0) | 2022.01.25 |
Learning Unreal 4 언리얼 공부일지 - 언리얼의 delegate (0) | 2022.01.24 |