언리얼엔진5 GAS - 기본 공격 판정방법 변경 2

조창근·2024년 9월 28일
0

언리얼엔진5 GAS

목록 보기
8/8
post-thumbnail

먼저 적용한 충돌처리 방법에는 어떤 문제가 있었을까?

처음 생각한 충돌처리 방법

기본공격 판정방법 변경 1
위 링크를 타고 들어 가면 애님스테이트를 활용해서 충돌처리를 적용하는 것을 확인해 볼 수 있습니다.

문제가 없었다고 생각했던 이유

부끄럽지만 솔직하게 말하면은 처음에는 당연히 문제가 없을 거라고 생각했습니다.
프레임이 떨어져도 과거의 제가 봤을 때는 어느정도 촘촘하게 라인트레이스가 나오는 게 보였고 이 정도면 충돌처리하는데 문제가 없겠다!라고 생각을 했습니다.

문제가 있다고 알게 된 과정

문제가 없겠지라고 생각은 했지만 이 마음속에 남아있는 이 찜찜함이 저를 못놔주고 있던 와중 언리얼 페스타를 가게 되었습니다.

네트워크 최적화,넥스트 스테이지의 언리얼 GAS사용법등 흥미로운 강연을 볼 수 있었고 시프트업의 스텔라 블레이드에서 활용한 여러가지 기법을 볼 수 있었습니다.
이제 본론으로 돌아와서 스텔라블레이드에서 충돌처리 기법에 대해서 설명을 해주었는데 정교한 충돌을 위한 방법을 설명해주었습니다.
애님스테이트를 활용하여 충돌처리를 진행하는 방법은 같았으나 이제 다음 스탭으로 프레임과 프레임 사이에 비어있는 공간에 대한 충돌처리를 어떻게 할 것인가에 대한 고민 및 해결 방법을 볼 수 있었습니다.
이 때 속마음으로는 와!이거다!하면서 좋아했던 기억이 있습니다.ㅋㅋㅋ

처음 방법의 문제

  1. 프레임이 떨어지게 되면 충돌처리가 발생하지 않을 수 있다.

  2. 공격속도가 빨라지게 되면 충돌처리가 발생하지 않을 수 있다.

    ->빈 공간이 현재 충돌처리가 안되는 부분

어떻게 해결해야 할까?

1.프레임과 프레임 사이를 삼각형으로 채운다

2. 프레임과 프레임 사이를 보간하여 라인트레이스를 촘촘하게 채워준다.

문제 해결하기

1. 프레임과 프레임 삼각형으로 채우기

  1. 현재는 칼의 시작지점과 끝 지점을 알고 있는 상태입니다.
  2. 중간 지점을 구하여 삼각형을 촘촘하게 만들 수 있도록 해줍니다.
    // Start와 End 위치의 중간 지점 계산
       FVector PrevMiddleLocation = (PrevStartLocation + PrevEndLocation) / 2;
       FVector CurrentMiddleLocation = (CurrentStartLocation + CurrentEndLocation) / 2;
    // 첫 번째 삼각형: PrevStart -> CurrentStart -> PrevMiddle
       PerformTriangleTrace(Owner, PrevStartLocation, CurrentStartLocation, PrevMiddleLocation, HitResults);

    // 두 번째 삼각형: CurrentStart -> CurrentMiddle -> PrevMiddle
       PerformTriangleTrace(Owner, CurrentStartLocation, CurrentMiddleLocation, PrevMiddleLocation, HitResults);

    // 추가 삼각형 1: PrevMiddle -> CurrentMiddle -> PrevEnd
       PerformTriangleTrace(Owner, PrevMiddleLocation, CurrentMiddleLocation, PrevEndLocation, HitResults);

    // 추가 삼각형 2: CurrentStartLocation -> PrevEnd -> CurrentEnd
       PerformTriangleTrace(Owner, CurrentMiddleLocation, PrevEndLocation, CurrentEndLocation, HitResults);
  1. 적용 결과

    -> 이렇게 삼각형으로 적용되는 것을 확인해 볼 수 있습니다.

2. 프레임과 프레임 사이를 보간하여 라인트레이스를 촘촘하게 채워준다.

1.전의 지점과 현재 지점을 거리의 비율에 맞게 보간하여 나누어 줍니다.

칼은 곡선으로 휘게 되는데 사진과 같이 직선으로 나오는 것을 확인해볼 수 있습니다.
다음 방법으로 이를 해결해보도록 하겠습니다.

2.칼의 곡선을 위해 베지어 곡선을 이용하여 보간해줍니다.

임의의 중간점과 보정값을 구하여 베지어 곡선을 만들어 줍니다.

  1. 중간점은 현재 라인과 이전 라인의 중간값을 구해줍니다.

  2. 중간점을 중간선의 방향벡터*보정값만큼 이동하여 줍니다.

  3. 보정값은 위 그림의 빨간선 길이 및 파란선 2개의 내적값을 구하여 추출해줍니다.

// 보간을 위해 이전 지점과 현재 지점 사이의 거리 계산
float DistanceStart = FVector::Dist(PrevStartLocation, CurrentStartLocation);
float DistanceEnd = FVector::Dist(PrevEndLocation, CurrentEndLocation);

FVector EndDirection = (CurrentEndLocation - PrevEndLocation).GetSafeNormal();
FVector StartDirection = (CurrentStartLocation - PrevStartLocation).GetSafeNormal();
float DotProduct = FVector::DotProduct(EndDirection, StartDirection);
float AngleRadians = FMath::Acos(DotProduct);

 // 라디안 값을 도 단위로 변환
float AngleDegrees = FMath::RadiansToDegrees(AngleRadians);
float AngleRatio =  180.0f/(AngleDegrees);
 // 보간할 간격(거리가 일정 이상일 경우 보간 수행)
float InterpolationStep = 5.0f; // 간격을 설정 

int32 NumStepsStart = FMath::CeilToInt(DistanceStart / AngleRatio);
int32 NumStepsEnd = FMath::CeilToInt(DistanceEnd / AngleRatio);
int32 NumSteps = FMath::CeilToInt(DistanceStart / InterpolationStep);


  // 2차 베지어 곡선을 위한 제어점 계산
FVector ControlPointStart = (PrevStartLocation + CurrentStartLocation) / 2 ; // 임의로 위로 올린 제어점
FVector ControlPointEnd = (PrevEndLocation + CurrentEndLocation) / 2 ;
FVector ControlPointDirection = (ControlPointStart - ControlPointEnd).GetSafeNormal();
ControlPointStart=ControlPointStart+ControlPointDirection*-NumStepsStart;
ControlPointEnd=ControlPointEnd+ControlPointDirection*-NumStepsEnd;
  
//베지어 커브 계산  
FVector InterpolatedStart = BezierCurve(PrevStartLocation, ControlPointStart, CurrentStartLocation, Alpha);
FVector InterpolatedEnd=BezierCurve(PrevEndLocation,ControlPointEnd,CurrentEndLocation,Alpha);

마무리

  1. 충돌 처리 방법을 보간하는 방법으로 바꿈으로서 보다 정확하게 판정할 수 있게 되었습니다.
  2. 정확한 판정을 위해서는 다양한 방법을 사용해야한다는 것을 알 수 있었습니다.
  3. 다음에는 AI와 GAS를 활용하는 방법을 연구해보도록 하겠습니다.

0개의 댓글