깃허브 주소
https://github.com/OneStone3647/ProjectT
유튜브 주소
https://www.youtube.com/watch?v=CMFbeRSMgVQ
신규 기능 추가
● 조작 UI
● Draw Debug 활성화 / 비활성화
● 새로운 Targeting(Disable Lock On Camera)
조작 UI
조작을 나타내는 UI가 추가되었습니다.
● 조작에 사용하는 기기는 다음과 같습니다.
○ PC -> 마우스와 키보드
○ PS4 -> DualShock4
Draw Debug 활성화 / 비활성화
디버그에 사용하는 Draw Debug의 활성화 / 비활성화 기능이 추가되었습니다.
● Targeting의 범위의 표시, Targetable Actor와 Target Actor의 구분을 나타내는 디버그에 사용하는 Draw Debug를 키보드의 'R'키, DualShock4의 'O'키로 활성화 / 비활성화 할 수 있습니다.
새로운 Targeting(Disable Lock On Camera)
새로운 Targeting이 추가되었습니다.
● 새로운 Targeting은 카메라가 Target을 바라보도록 고정하지 않고 자유롭게 카메라를 조작할 수 있습니다.조작에 사용하는 기기는 다음과 같습니다.
● 새로운 Targeting을 사용하기 위해서는 다음과 같은 조작이 필요합니다.
○ 키보드에서는 'T'키, DualShock4에서는 '□'키를 입력하여 Lock On Camera를 비활성화 합니다.
● 새로운 Targeting은 카메라의 조작으로 Target을 변경할 수 없으므로 Target을 변경하기 위해서는 다음과 같은 조작이 필요합니다.
○ 키보드에서는 '왼쪽 Ctrl'키, DualShock4에서는 'L1'키를 누른 상태에서 Camera를 좌우로 조작합니다.
기존 Targeting(Enable Lock On Camera)와 새로운 Targeting(Disable Lock On Camera)의 차이
기존의 Targeting은 플레이어와 현재 Target의 방향벡터와 플레이어와 새로운 Target의 방향벡터를 내적하여 Target을 변경했습니다.
새로운 Targeting은 플레이어의 카메라와 새로운 Target의 방향벡터를 플레이어의 카메라와 새로운 Target의 방향 벡터를 플레이어의 카메라의 전방벡터에 외적한 값을 플레이어 카메라의 Up벡터에 내적하여 Target을 변경합니다.
EPTTargetDirection UPTTargetingSystemComponent::WhichSideOfTarget(AActor* NewTargetableActor) const
{
// 카메라를 Target에게 고정하는 LockOn일 경우
// Target과 플레이어의 내적을 기준으로 구분합니다.
if(bLockOnCamera)
{
const FVector TargetActorDirection = UKismetMathLibrary::GetDirectionUnitVector(PlayerCameraManager->GetCameraLocation(), Target->GetActorLocation());
const FVector NewTargetableActorDirection = UKismetMathLibrary::GetDirectionUnitVector(PlayerCameraManager->GetCameraLocation(), NewTargetableActor->GetActorLocation());
const FVector NewDirection = UKismetMathLibrary::Cross_VectorVector(TargetActorDirection, NewTargetableActorDirection);
const float NewDot = UKismetMathLibrary::Dot_VectorVector(NewDirection, GetOwner()->GetActorUpVector());
if(NewDot >= 0.0f)
{
return EPTTargetDirection::TargetDirection_Right;
}
return EPTTargetDirection::TargetDirection_Left;
}
// 카메라를 Target에게 고정하지 않는 LockOn일 경우
// 화면을 기준으로 구분합니다.
const float TargetDot = CalculateDotProductToTarget(Target);
const float NewTargetDot = CalculateDotProductToTarget(NewTargetableActor);
if(TargetDot >= NewTargetDot)
{
return EPTTargetDirection::TargetDirection_Left;
}
return EPTTargetDirection::TargetDirection_Right;
}
float UPTTargetingSystemComponent::CalculateDotProductToTarget(AActor* NewTargetableActor) const
{
if(!NewTargetableActor)
{
return 0.0f;
}
// 카메라를 Target에게 고정하는 LockOn일 경우
if(bLockOnCamera)
{
const FVector TargetActorDirection = UKismetMathLibrary::GetDirectionUnitVector(GetOwner()->GetActorLocation(),Target->GetActorLocation());
const FVector NewTargetableActorDirection = UKismetMathLibrary::GetDirectionUnitVector(GetOwner()->GetActorLocation(),NewTargetableActor->GetActorLocation());
return UKismetMathLibrary::Dot_VectorVector(TargetActorDirection, NewTargetableActorDirection);
}
// 카메라를 Target에게 고정하지 않는 LockOn일 경우
else
{
if(PlayerCameraManager)
{
const FVector NewTargetableActorDirection = UKismetMathLibrary::GetDirectionUnitVector(PlayerCameraManager->GetCameraLocation(),NewTargetableActor->GetActorLocation());
const FVector CrossProduct = UKismetMathLibrary::Cross_VectorVector(PlayerCameraManager->GetActorForwardVector(), NewTargetableActorDirection);
return UKismetMathLibrary::Dot_VectorVector(PlayerCameraManager->GetActorUpVector(), CrossProduct);
}
}
return 0.0f;
}
AActor* UPTTargetingSystemComponent::FindDirectionalTarget(EPTTargetDirection NewTargetDirection)
{
AActor* NewTarget = nullptr;
TArray<AActor*> TargetableActors = SearchTargetableActors();
const int32 CurrentTargetIndex = TargetableActors.Find(Target);
// 현재 Target이 TargetableActors 배열에 존재할 경우 배열에서 제거합니다.
if(CurrentTargetIndex != INDEX_NONE)
{
TargetableActors.Remove(Target);
}
// 현재 Target을 기준으로 좌우에 있는 Target을 탐색합니다.
TArray<AActor*> LeftTargetableActors;
TArray<AActor*> RightTargetableActors;
for(AActor* TargetableActor : TargetableActors)
{
APTDummyCharacter* TargetablePRAICharacter = Cast<APTDummyCharacter>(TargetableActor);
if(IsValid(TargetablePRAICharacter) == true && TargetablePRAICharacter->IsDead() == false)
{
switch(WhichSideOfTarget(TargetablePRAICharacter))
{
case EPTTargetDirection::TargetDirection_Left:
LeftTargetableActors.AddUnique(TargetablePRAICharacter);
break;
case EPTTargetDirection::TargetDirection_Right:
RightTargetableActors.AddUnique(TargetablePRAICharacter);
break;
default:
break;
}
}
}
// 카메라를 Target에게 고정하는 LockOn일 경우
if(bLockOnCamera)
{
// 두 벡터가 이루는 각이 클수록 두 벡터의 내적은 작습니다.
switch(NewTargetDirection)
{
case EPTTargetDirection::TargetDirection_Left:
if(LeftTargetableActors.Num() > 0)
{
// 왼쪽에서 내적이 가장 큰 Target
NewTarget = GetTargetByDotProduct(LeftTargetableActors, true);
}
else
{
// 오른쪽에서 내적이 가장 작은 Target
NewTarget = GetTargetByDotProduct(RightTargetableActors, false);
}
break;
case EPTTargetDirection::TargetDirection_Right:
if(RightTargetableActors.Num() > 0)
{
// 오른쪽에서 내적이 가장 큰 Target
NewTarget = GetTargetByDotProduct(RightTargetableActors, true);
}
else
{
// 왼쪽에서 내적이 가장 작은 Target
NewTarget = GetTargetByDotProduct(LeftTargetableActors, false);
}
break;
default:
break;
}
}
// 카메라를 Target에게 고정하지 않는 LockOn일 경우
else
{
switch(NewTargetDirection)
{
case EPTTargetDirection::TargetDirection_Left:
if(LeftTargetableActors.Num() > 0)
{
NewTarget = GetTargetByDotProduct(LeftTargetableActors, true);
}
else
{
NewTarget = GetTargetByDotProduct(RightTargetableActors, true);
}
break;
case EPTTargetDirection::TargetDirection_Right:
if(RightTargetableActors.Num() > 0)
{
NewTarget = GetTargetByDotProduct(RightTargetableActors, false);
}
else
{
NewTarget = GetTargetByDotProduct(LeftTargetableActors, false);
}
break;
default:
break;
}
}
if(IsValid(NewTarget) == true)
{
return NewTarget;
}
return nullptr;
}
기존의 Targeting으로 현재 Target에서 오른쪽에 있는 Actor로 Target을 변경하게 되면 현재 Target 다음으로 내적 값이 큰 Actor가 Target이 됩니다.
새로운 Targeting으로 Target을 변경할 경우 오른쪽에서 내적이 가장 작은 Actor가 Target이 됩니다.
'Project > T' 카테고리의 다른 글
[Project T] Unreal Targeting System / 언리얼 타겟팅 시스템 v1.2.0 (0) | 2022.08.10 |
---|---|
[Project T] Unreal Targeting System / 언리얼 타겟팅 시스템 v1.0.0 (0) | 2022.04.25 |
Unreal TargetLock System Prototype / 언리얼 타겟락 시스템 프로토타입 (0) | 2020.09.19 |