이제 타겟된 액터에게 회전을하고 타겟을 바라보면서 움직이는걸 구현해 본다.

TargetLockOn이라는 함수를 만들고 이 함수에 만들었던 함수를 호출시켜준다.

BeginPlay를 상속받고 BeginPlay 에서 자기자신의 액터와 컨트롤러를 받아와 주었다.

 

SetControllerRotation함수를 만들어주며 LockOn이 되었을때 컨트롤러의 IgnoreLookInput와 폰의 컨트롤러를 false로 만들게되면 마우스로 움직일때 컨트롤러가 움직이지 않게 된다.

위젯또한 함수와 시켜 만들어주고 방금만든 SetControllerRotation과 CreateWidgetTargetMark를 LockOn에서 호출시켜 주게 만들어 주었다.

 

UpdateControllerRotation함수를 만들어 주었고 여기에서 컨트롤러를 회전시켜 타겟에 고정시켜주었다.

타겟 벡터와 나 자신의 벡터를 빼고 정규화해주면 타겟으로부터 방향을 구할 수 있다.

그리고 방향을 통해 회전을 구해주며 적절한 수치를 이용하여 타겟과 멀어지면 TargetOff를 시키고

LockOn범위 내에있으면서 타겟과 가까워지게 되면 컨트롤러의 pitch값을 회전시켜 몰입감을 더 줄수 있게 된다.

이것을 Interp함수를 통해 값을 구하고 컨트롤러를 세팅해준다.

 

마지막으로 TargetOff함수에 추가적인 부분을 수정하였다.

 

 

UpdateControllerRotation는 Tick에서 실행시켜주고 컴파일 후 실행해보면 타겟고정이 잘되며 가까이 가면 컨트롤러의 Pitch 도한 회전을 하게 되는걸 볼 수 있다.

 

 

이제 GetAllActots 함수를 통해 월드에 배치된 액터(Enemy)를 가져 올 수 있게 되었다.

배치된 액터들 중에서 가장 가까운 액터를 찾을 수 있는 함수를 만들어 주었다.

OwnerActor, NearTarget이란 Actor변수를 만들어주고 BeginPlay에서 OwnerActor를받아와주고 TargetMaxDistance 를 선언해주며 이는 타겟과의 거리의 맥시멈 수치이다. 그리고 FindNearTarget이라는 함수를 만들었으며 이는 가장 가까운 적을 찾아주는 함수이다.

타겟과 나자신의 거리를 구하기 위한 함수를 만들었으며 TargetActors를 받아온걸 한번씩 반복문을 통해 돌아가면서 제일 낮은 액터를 찾아준다.

 

그런다음 TargetLockOn함수에 만들었던 함수를 통해 구현을 해주었다.

이제 실행 후 테스트를 할수 있게 세팅을 해주고 타겟시스템을 실행하면 가장 가까운적을 식별 할 수 있게 되었다.

 

여기서 문제가 되는 부분이 존재하게 되는데 TargetInterface를 가진 액터들은 다 식별하여 장애물이 존재해도 타겟을 하게 되어진다 그래서 이를 해결위해 LineTarce를 사용하여 장애물 뒤쪽에 존재하는 액터들은 식별을 못하게 해주었다.

LineTraceForTarget 이라는 함수를 만들어주고 라인트레이스를 쏴서 히트가 되는 액터만 식별해 주었다.

 

기존에 FindNearTarget을 이용해 찾았던 곳 윗부분에 라인트레이스를 활용한 함수를 사용하여 바꿔주었다.

컴파일 후 실행하여 벽을 만들고 락온 시스템을 켜주면 벽뒤는 무시되며 라인트레이스에 적중한 액터중 제일 가까운 적을 식별할 수 있게 되었다

캐릭터의 블루프린트 클래스로 돌아와 기존에 만들어두었던 LockedOnWidgetClass를 설정해주었다

 

TargetLockOn에서 위젯컴포넌트를 생성해 Enemy몸통에 달아준다

달아주기위해 지금 쓰고있는 Grux메쉬의 가운데부분은 pelvis가 가까워 pelvis로 attach를 해주었다

 

마지막으로 TargetOff에 위젯컴포넌트를 DestroyComponent함수를 통해 없애주었다

이제 실행후 TargetOn을 해보면 가장 가까운적에게 하얀색 마크가 생성이 되며 TargetOff를 통해 지워주고

다시 가까운적에게 가서 TargetOn을하면 가까운적에게 마크가 생성이 되는걸 볼 수 있다.

 

 

먼저 액터 컴포넌트로 TargetSystemComponent와 언리얼 인터페이스로 TargetSystemInterface를 만들주었다.

단순히 순수 가상함수를 만들어 주고 이는 나중에 Enemy에 추가하여 사용할 인터페이스 이다.

 

타겟이 되면 간단히 식별할수 있는 UserWidget을 만들어 주었다.

Enemy 클래스로 돌아와 TargetSystemInterface를 상속받아주고 가상함수를 구현해주었다. 가상함수 내용은 true 리턴해주었다.

 

TargetSystemComponent클래스에서 위젯을 사용하기 위해 받아올 변수를 만들어 주고 TargetLockOn함수와 TargetLockOff함수를 선언 및 정의를 해주었다.

 

제일 먼저 월드에 속한 액터를 검색하여 타겟대상 들인 액터를 순회하는 TActorIterator를 이용하였다.

TActorIterator를 통해 Actor를 가져오고 Actor의 Interface가 존재하는지 체크를 Actors에 넣어주었다.

캐릭터 클래스에서 방금만든 TargetSystemComponent를 만들어주고 테스트 할수있게 세팅을 해주었다.

 

캐릭터 이벤트 그래프에서 TargetSystem의 GetAllActos를 사용할수 있게 노드를 만들어 주고

뷰포트에 몬스터들을 5마리 배치시키고 시작하여 1번을 누르면 5마리의 액터의 이름이 표시되는걸 볼 수 있다.

 

기존에 만들었던 CharacterBase클래스를 통해 Enemy클래스를 만들어 주었다.

CharacterBase클래스엔 캐릭터가 가져야할 공통적인 정보들이 있어 Enemy를 만들 수 있다.

필요한 변수와 함수를 만들어 주었다.

 

CharacterBase에서 상속받은 AbilitySystemComponent와 Attribute를 메모리 할당시켜주고

BeginPlay에서 Ability를 초기화 시켜주고 Attribute에서 Health를 Delegate로 바인딩 해주었다.

 

HealthBarWidget은 캐릭터와 동일하다. 이것 또한 블루프린트화 시켜주고 ProgressBar를 추가시켜주었다.

 

Enemy클래스를 블루프린트화 시켜주고 준비해둔 메쉬를 설정해준 뒤 블루프린트에서 HealthBarWidgerComponent 디테일 창에서 위젯 클래스를 지정해준다.

 

이제 뷰포트에 Enemy를 만들어주고 실행시켜보면 HealthBar와 Enemy가 존재되었다.

 

Enemy의 HealthWidget에 시각적으로 보이니 카타나 기본공격을 통해 데미지를 주어 Health에 영향을 줄 수 있게 되었다.

먼저 카타나 무기에 데미지를 줄수있는 효과핸들의 변수를 선언 및 함수기능을 만들어 주었다.

그리고 카타나 스킬을 쓸때 효과를 줄수있는 이펙트를 만들고 디테일에서 Modifiers에 인덱스를 추가해주고 Health에 대해 Add로 -5의 값을 설정 해주었다.

 

이제 BaseAttack함수 방금 만든 이펙트를 저장시켜줄 변수와 BaseAttack함수에서 핸들을 만든 뒤 카타나의 핸들에 저장시켜 주었다.

 

마지막으로 카타나의 콜리전에 Enemy가 닿을 시 충돌을 감지할 수 있는 Collision을 만들어주었다.

카타나의 콜리전 상태이다.

 

카타나 공격 몽타주에서 사용할 노티파이를 만들어 주었다.

 

그런다음 몽타주에서 필요한 프레임구간에 노티파이를 설정해주었다.

 

이제 게임을 플레이 해보면 몬스터의 체력이 줄어들는게 보이게 되었다. 또는 Debug를 통해서도 볼수 있었다.

 

 

모션 워핑은 캐릭터의 루트 모션이 타깃과 일치시켜 준다.

캐릭터가 북쪽을 바라보고 공격을 하고있는데 공격이 끝나는 동시에 키보드를 왼쪽을 누르면 공격하면

왼쪽을 바라보고 공격을 할 수 있게 해준다.

먼저 플러그인에서 모션워핑을 찾아 추가해주고 재시작을 해주었다.

C++에서도 사용할수 있도록 모듈을 추가해 주었다.

 

캐릭터 클래스에 MotionWarpingComponent를 추가해주고 생성자에서 메모리 할당을 시켜주고

외부에서 쓸수있게 Get함수를 만들어주었다.

 

어빌리티 능력에 UpdateMotionWraping 함수를 만들어주고 KatanaBaseAttack 블루프린트에 UpdateMotionWarping함수 노드를 가져와 사용해주었다.

 

그런다음 KatanaAttackMontage에서 노티파이구간에 모션워핑을 추가시켜고 모션워핑에 대한 옵션을 세팅해주었다.

TargetName은 TargetWarp로하고 캐릭터가 방향만 바꿀것이라 Translation은 체크를 풀고 Warp Rotation만 체크를 해주고 Type은 Facing으로 해주었다.

 

이제 실행을 해보면 아래의 동영상처럼 캐릭터가 때리고 난 후 키보드 방향을 바꾸고 때리면 도중에 방향을 바꿀 수 있게 되었다.

 

캐릭터가 움직일때 너무 딱딱해보여 SpringArm의 기능중 카메라 랙을 설정해서 카메라를 스무스하게 움직이는 설정을 추가해 좀 자연스럽게 만들어 주었다.

 

게임 어빌리티 능력을 사용하기 위해 먼저 GameplayAbility 와 AbilitySystemComponent를 상속받아 클래스를 만들어 주었다. AbilitySystemComponent에서는 전에 만들어 두었던 PlayerController의 입력부분에 입력받고 AbilitySystemComponent 에서 처리를 시켜주게 만들어주었다.

 

방금 만든 BVAbilitySystem를 상속받아 KatanaBaseAttack 클래스를 만들어 주었다.

 

AbilitySystem을 사용하기위해 Tag를 자주 사용하기때문에 전역변수로 사용할 수 있게 만들어 주었다.

디자인패턴중 싱글톤 패턴이다.

 

이제 애니메이션 몽타주에서 사용할 AnimNotify클래스를 상속받아 NextAttackCheck와 EndAttackCheck클래스를 만들어주었다. 

 

준비해둔 애니메이션 시퀀스를 이용해 몽타주를 만들어 주었다.

총3개의 공격모션이 필요하기때문에 섹션 이름에 Attack1,Attack2, Attack3을 만들어 주고 애님 노티파이를 만들었던 클래스에 알맞은 타이밍에 맞게 NextAttackCombo와 EndAttackCombo를 설정해 주었다.

 

애니메이션 블루프린트에서 슬롯을 추가해 연결시켜 주었다.

 

KatanaBaseAttack 클래스를 이용해 블루프린트를 만들고 설정 해주었다.

카타나의 기본공격은 좌클릭으로 할것이기때문에 LMB를 설정 해주었다.

 

이제 게임을 플레이해보면 콤보공격이 이루어 지고있다.

 

 

+ Recent posts