이전에 구현해 둔 BT의 Sequence 부분에 공격 노드를 추가하려고 한다.
그 전에 적의 공격을 어떻게 할까
적은 이렇게 생겼고,
오버워치1 자리야의 우클릭 공격처럼
원형의 포탄을 낮은 포물선으로 발사
하도록 하고 싶다.
발사를 하기 위해선, 플레이어와 일정 거리 떨어져서 멈춘 뒤
,
공격을 하게 하고 싶다.
1 Projectile을 CPP Actor로 생성하고,
BP로 상속받아 Projectile Movement와 더불어
Collision, Mesh의 설정까지 하였다.
2 Enemy CPP에서 Shoot 함수를 만들었다.
BT TaskNode에선 해당 Shoot만 실행하도록 할 것이다.
Shoot을 위해서 Enemy BP에 Projectile을 연결하였고,
스켈레탈매시의 Muzzle 소켓에서 Projectile이 발사되도록 하였다.
3 문제 발생
Projectile이 world의 details탭에 생성되는 건 보이지만,
화면상 보이지가 않았다. 아래의 문제 때문으로 보인다.
https://dev.epicgames.com/community/learning/tutorials/Dl70/unreal-engine-texture-streaming-pool-guide-fix-over-budget-issues-optimize-your-textures
r.streaming.pool.size 2000
콘솔 명령어로 해결하였다.
4 ProjecTile의 설정과 Movement관련 함수를 작성하여 발사되도록 하였다.
5 BT를 적절히 수정한다. 특정 거리에서 멈추고 공격하고 따라오고
거리가 특정 거리면 멈추도록 해야하는데, BB 변수나 TaskNode를 새로 생성해야만 한다.
우선 바보 같이 진행했던 알고리즘을 수정했다.
Idle과 Jog의 State변환에 있어서 BB의 IsChased값을 사용했는데,
그냥 속도를 계산하고, 움직이면 Jog로 애니메이션을 실행하면 되었다.
그리고 Enemy가 플레이어의 방향을 보는 BP를 수정했다.
이전에 사용했던 CSV 파일을 이용한다.
여기서 DropExp는 Character가 사용하지 않을 것이다.
이전 프로젝트에선 Character를 Enemy로도 사용하였다
GameInstance 속에는 GameInstance클래스와 별개로
CSV를 담을 구조체를 생성해 둔다.
그렇게 되면, CSV파일을 import시 구조체를 선택할 수 있게 된다.
구조체의 형식에 맞게 DataTable이 생성이 된다.
GameInstance는 Data를 담을 구조체만 생성했던 것이고,
실제 Data를 적용시키기 위해, DataTable을 GameInst와 연동한다.
ActorComponent를 만든다. CharacterStatComponent라고 이름 짓는다.
GameInstance는 단순히 공용 정보를 저장해두는 공간이고,
CharacterStatComponent는 Character마다 가지게 되는
정보를 담을 Component로 둘 것이다.
따라서 Hp, Level이 GameInstance를 참고하여 처음에 적용되게 된다.
위는 오류가 발생한 부분인데, 생성자에 작성해야만 한다.
Enemy의 SetDamage는 Player의 LineTrace로부터 실행된다.
CharacterStat에는 SetDamage
로 인자로 들어온 대미지만큼 CurrentHP를 깎도록 하였다.
SetDamage
로 계산한 CurrentHP의 값이
0 이하라면, Delegate를 호출하도록 하였다.
해당 Delegate는 Player나 Enemy에서
AddUObject로 바인딩 하였다.
OnHpIsZeroFunc이 실행되도록 하였고,
죽음과 관련된 기능이 실행된다.
Controller를 분리하고,
Timer로 3초 뒤에 Destroy되게 하였다.
Player의 SetDamage는 Projectile로부터 실행되게 한다.(TakeDamage)
그리고 Player도 Enemy와 똑같이 Controller를 없애고,
3초 뒤에 사라지도록 했다.
하지만 아래의 구문에서 오류가 발생한다.
아마 BT로 Overlap된 Actor를 SpCharacter로 캐스트 할 수 있음에도,
Controller만 쏙 사라졌으니 GetController가 nullptr이라
발생하는 오류로 보인다.
PlayerController인지 굳이 확인할 필요는 없었다.
아래처럼 수정.
만들고 보니,
Projectile을 한 번 맞았는데 연속해서 피가 달고,
맞았는데도 안 다는 경우도 있었다.
흠..
NotifyHit 말고,
- NotifyHit이 왜 제대로 동작하지 않은건지... 전혀 모르겠다.
- 혹시 몰라서 Projectile의 InitialSpeed를 줄여보고
Collision Preset도 따로 적용하고,
Collision 크기도 수정해 보았는데, 원인을 도무지 모르겠다.