내용
스킬키 만들어서 해당 스킬 사용하면 주변 몬스터 탐색 후 Occlusion, 4초 후 해제.
스킬 발동 시. 몬스터만 충돌되는 "Player Attack" Trace Channel을 이용하여
OverlapMultiByChannel으로 범위안에있는 충돌체 저장 후. 그 안에서 또
Monster만 별도 변수에 저장과 동시에 탐지된 몬스터 Occlusion 활성화.
GetWorldTimerManager().SetTimer() 함수를 이용해 4초뒤
Monster만 따로 저장된 변수를 이용하여 Occlusion 해제.
AKnightCharacter::AKnightCharacter()
{
//배열 초기화
ResultArray.Init(FOverlapResult(),0);
ResultArray2.Init(FOverlapResult(), 0);
}
void AKnightCharacter::BeginPlay()
{
Super::BeginPlay();
//탐지 스킬 관련정보 저장 및 배열 추가.
SkillInfo.SlotNumber = 1;
SkillInfo.SkillNumber = 1;
SkillInfo.Damage = 0;
SkillInfo.SkillActor = nullptr;
SkillInfo.SkillEtc = 10000;
mSkillInfoArray.Add(SkillInfo);
}
void AKnightCharacter::Skill2()
{
//SkillNumber 못찾을시 안전트리거용
int32 SkillNumber = -1;
//해당 스킬슬롯에 있는 스킬 넘버 불러오기
int32 Count = mSkillInfoArray.Num();
for (int32 i = 0; i < Count; ++i)
{
if (mSkillInfoArray[i].SlotNumber == 1)
{
SkillNumber = mSkillInfoArray[i].SkillNumber;
break;
}
}
//스킬넘버가 없으면 종료
if (SkillNumber == -1)
return;
//해당 스킬넘버 Animation 실행.
mAnimInst->UseSkill(SkillNumber);
}
void AKnightCharacter::UseSkill(int32 SkillNumber)
{
int32 Count = mSkillInfoArray.Num();
//탐색 스킬 사용시.
if (SkillNumber == 1)
{
PrintViewport(1.f, FColor::Red, TEXT("Skill 2 Enable"));
//자신을 제외하기 위한 파라미터 설정
FCollisionQueryParams param(NAME_None, false, this);
float skillEtc = NULL;
//탐색 스킬 범위 값 불러오기.
for (int32 i = 0; i < Count; ++i)
{
if (mSkillInfoArray[i].SkillNumber == 1)
skillEtc = mSkillInfoArray[i].SkillEtc;
}
//탐색 범위 안에 Overlap된 몬스터 정보 저장.
//탐색 범위 및 Trace채널 설정
bool CollisionEnable = GetWorld()->OverlapMultiByChannel(ResultArray, GetActorLocation(), FQuat::Identity, ECollisionChannel::ECC_GameTraceChannel3,
FCollisionShape::MakeSphere(skillEtc), param);
//직관적으로 보기위해 Draw Debug 설정
#if ENABLE_DRAW_DEBUG
FColor DrawColor = CollisionEnable ? FColor::Red : FColor::Green;
DrawDebugSphere(GetWorld(), GetActorLocation(), skillEtc, 20, DrawColor, false, 0.3f);
#endif
if (CollisionEnable)
{
Count = ResultArray.Num();
AMonster* Monster = nullptr;
for (int32 i = 0; i < Count; ++i)
{
Monster = Cast<AMonster>(ResultArray[i].GetActor());
if (IsValid(Monster))
{
ResultArray2.Add(ResultArray[i]);
Monster->OnRender(true, 26);
}
}
ResultArray.Init(FOverlapResult(), 0);
}
FTimerHandle TimerHandle;
//FTimerDelegate SkillTimer = FTimerDelegate::CreateStatic(this, &AKnightCharacter::Skill2End,void);
GetWorldTimerManager().SetTimer(TimerHandle, this, &AKnightCharacter::Skill2End, 4.f, false);
//스킬 1번 사용시. 2번은 엑터를 사용안하기에 별도 코드로 구현
for (int32 i = 0; i < Count; ++i)
{
if (mSkillInfoArray[i].SkillNumber == SkillNumber)
{
if (SkillNumber == 1)
break;
FActorSpawnParameters SpawnParam;
SpawnParam.Template = mSkillInfoArray[i].SkillActor;
SpawnParam.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
ASkillProjectile* Skill =
GetWorld()->SpawnActor<ASkillProjectile>(GetActorLocation() + GetActorForwardVector() * 100.f,
GetActorRotation(), SpawnParam);
break;
}
}
}
void AKnightCharacter::Skill2End()
{
if (ResultArray2.Num() != 0)
{
int32 Count = ResultArray2.Num();
AMonster* Monster = nullptr;
for (int32 i = 0; i < Count; ++i)
{
Monster = Cast<AMonster>(ResultArray2[i].GetActor());
if (IsValid(Monster))
{
Monster->OnRender(false);
}
}
ResultArray2.Init(FOverlapResult(), 0);
}
}
[Monster.h]
public:
void OnRender(bool On,int32 Color = 16);
[Monster.cpp]
void AMonster::OnRender(bool On, int32 Color)
{
GetMesh()->SetRenderCustomDepth(On);
GetMesh()->SetCustomDepthStencilValue(Color);
}