Sputnik(5) - Attack

JUSTICE_DER·2023년 10월 11일
0

🛰Sputnik (Satellite)

목록 보기
8/9

1. 피격

  • 플레이어가 공격 당하는 기능을 위해서는 아래가 필요할 것이다.
    1 적의 BT를 수정하고, 공격 Anim과 공격 범위의 설정
    2 플레이어의 HP 설정
    3 플레이어의 UI 설정
    4 플레이어의 죽음 Anim 설정
    5 GameMode의 GameOver 설정

1-1. 적의 공격 (BT / Anim)

이전에 구현해 둔 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를 수정했다.

1-2. 캐릭터의 피격(Anim / HP)

  • 우선 피격시에는 캐릭터의 HP가 줄어들어야 할 것이다.
  • CSV파일을 만들어 캐릭터의 레벨과 그에 맞는 HP나 능력치를 넣어보자.
  • HP가 0 이하로 내려가면, Dead Anim을 실행해야 할 것이다.
  • 그리고 Collision 없애고, Actor 없애고,
    GameMode에서 Game을 끝내고.. 잡다한 설정까지 해야할 것이다.
  • 그리고 그 HP를 보여줄 UI까지 구현하면
    피격에 대한 캐릭터로부터의 구현사항은 더 없을 것이다.

A. Character Stat

이전에 사용했던 CSV 파일을 이용한다.
여기서 DropExp는 Character가 사용하지 않을 것이다.
이전 프로젝트에선 Character를 Enemy로도 사용하였다

  • 우선 Character Stat을 담기 위해 일반적으로 생성하는
    GameInstance를 만들어 ProjectSetting에 적용시킨다.
  • GameInstance 속에는 GameInstance클래스와 별개로
    CSV를 담을 구조체를 생성해 둔다.
    그렇게 되면, CSV파일을 import시 구조체를 선택할 수 있게 된다.
    구조체의 형식에 맞게 DataTable이 생성이 된다.

  • GameInstance는 Data를 담을 구조체만 생성했던 것이고,
    실제 Data를 적용시키기 위해, DataTable을 GameInst와 연동한다.

  • ActorComponent를 만든다. CharacterStatComponent라고 이름 짓는다.
    GameInstance는 단순히 공용 정보를 저장해두는 공간이고,
    CharacterStatComponent는 Character마다 가지게 되는
    정보를 담을 Component로 둘 것이다.
    따라서 Hp, Level이 GameInstance를 참고하여 처음에 적용되게 된다.

위는 오류가 발생한 부분인데, 생성자에 작성해야만 한다.

B. 피격 시스템

  • 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 말고,

    • NotifyActorBeginOverlap을 사용하여
    • LiveCoding 말고 Development Editor로 빌드해야 해결..
    • 당연히 적절한 Collision Preset을 설정하고 적용시켰다.
    • NotifyHit이 왜 제대로 동작하지 않은건지... 전혀 모르겠다.
    • 혹시 몰라서 Projectile의 InitialSpeed를 줄여보고
      Collision Preset도 따로 적용하고,
      Collision 크기도 수정해 보았는데, 원인을 도무지 모르겠다.
profile
Time Waits for No One

0개의 댓글