
PullTrigger 리팩터링이제 총기 사운드를 넣어줄 것인데, 이에 앞서서 Gun 클래스에 위치한 PullTrigger 함수를 리팩토링 해줄 것이다.총기 사운드 특성상 해당 함수에 기능을 넣게 되는데, 지금도 해당 함수가 상당히 길기 때문에 가독성을 높이기 위해 미리 작업을 해주자. 우리가 함수로 분리할 부분은 크게 2가지로 Trace하는 내용과 OwnerController를 얻는 부분이다. OwnerController의 경우 Trace 함수에서도 체크가 필요한 부분이기 때문에 우선적으로 구현해주자.PullTrigger 함수 상단에 적었던 내용을 그대로 복사하여 넣고, 해당 OwnerPawn이 nullptr인지 아닌지만 각 함수에서 체크해주게 된다. 이제 Trace 하는 부분이다.해당 함수의 인풋인 H..

승리 조건 계산하기EndGame 함수를 통해 승리 케이스를 구현할 수 있도록 만들었으니,이제 패배 조건과 마찬가지로 승리 조건 또한 구현해주자. 우선 승리 조건은 AI가 모두 죽었을 때이다.따라서 AIController 클래스에서 죽었는지 여부 체크를 위한 IsDead() 함수를 만들어주자. 해당 함수에서 ShooterCharacter2 클래스에서 죽는 조건으로 이미 만들었던 IsDead() 함수를 호출해준다. 그리고 이제 이겼을 때 화면을 제작해주어야 한다.우선 PlayerController 클래스에서 선언해주자. 그리고 bIsWinner 값을 토대로 이겼을 때, 졌을 때를 구분하여 화면을 할당해주자. 이제 컴파일 하고 돌아가서 위젯을 생성해주자.기존 졌을 때 위젯을 복사하여 내용이랑 색깔만 변경해주었..

액터 반복하기현재 플레이어 컨트롤러에 대해서만 GameHadEnded 함수를 호출하고 있다.하지만 AI 에게도 마찬가지로 게임이 종료되었음을 알려줄 필요가 있다.이를 위해서 레벨에 존재하는 모든 컨트롤러에 대해 접근을 할 수 있어야 하는데, TActorRange 템플릿 클래를 통해 하게 된다. 우선 누가 이겼는지 판별을 위해 게임 종료 함수를 새롭게 만들어주자. 그리고 TActorRange를 통해 레벨에 존재하는 컨트롤러를 모두 찾게 된다.템플릿 클래스이므로 템플릿에 목표 대상인 AController를 넣어주고,for 반복문을 통해 모든 컨트롤러에 대해 접근하게 된다. 이후 해당 컨트롤러가 AI인지, 플레이어인지 체크하기 위해 IsPlayerController 함수를 사용하여 판별해주고,해당 함수를 통해..

패배 화면 띄우기지금은 패배시 아무것도 뜨지 않고 5초 후에 레벨이 재시작된다.완성도를 높이기 위해 패배시 화면에 출력될 UI를 만들어보자. 이를 위해 우선 UI 폴더를 생성하고 위젯 블루프린트를 생성하자.그리고 이어서 화면에 띄울 Text를 생성해주자. 텍스트는 우측 디테일 패널을 통해 위치 앵커 설정, 색상, 글씨 크기 등이 조정 가능하다. 이제 해당 위젯을 출력하기 위해 PlayerController 클래스를 통해 해당 위젯을 설정하자.헤더에서는 TSubclassOf 클래스로 위젯을 설정하여 위젯만 할당하도록 범위를 제한해주었다. 이후 CreateWidget() 함수를 통해 위젯을 생성하고, AddToViewport() 함수를 이용하여 화면에 출력하도록 하자. 컴파일 하기에 앞서서 추가로 해야할 작..

C++에서 타이머 설정하기게임 종료에 대해서 더 구체화를 해보도록하자.기존에 PawnKilled를 통해 폰이 죽었을 시 로그메시지가 뜨도록 했지만, 이번에는 PlayerController에 속한 함수인 GameHasEnded 함수를 통하여 플레이어가 죽었을시 게임이 종료되는 로그메시지를 출력해보도록 하자. 이를 위해 PlayerController를 우선 얻고, 해당 컨트롤러를 통해 GameHadEnded 함수를 호출한다.해당 함수는 해당 플레이어에 대한 포커스 포인터와 bool 값(승패 여부)를 필요로 하는데, 여기서 포커스 기능은 필요없으므로 null로 넘겨준다. 그리고 이제 GameHadEnded 함수를 오버로딩해서 사용하기도하고, 레벨을 다시 시작하는 등의 동작 구현을 위해 PlayerControl..

게임 종료하기이제 전반적인 기능을 만들었으니, 게임을 종료하는 방법도 다뤄보자.이와 관련된 클래스는 게임모드에서 다루게 된다. 게임모드는 게임과 관련된 규칙을 다루게 되기 때문에 기본적인 죽음에 대한 PawnKilled 함수를 기본 게임모드에 virtual로 생성하고, 또 다른 게임모드를 만들어 해당 함수에 오버라이딩하도록 구현할 것이다.우선 강의에서는 C++로 생성하였기 때문에 게임모드가 있다고 하였으나 놓친 부분이 있는지 내 환경에는 보이지 않아 따로 만들어주었다. 여기서 이제 Pawnkilled 함수를 구체적 내용은 구현하지 말고 몸체만 선언해주자. 이제 해당 게임모드를 기반으로 다시 오버라이딩 할 서브 게임모드를 만들어주자. 그리고 해당 게임모드 클래스에 PawnKilled를 호출해야 할 위치를 ..

라인트레이스에서 액터 무시하기저번에 강의에서 AI가 총을 자기 자신에게 쏘는 것을 볼 수 있었다.이번엔 해당 오류를 고쳐보자. 이를 위해 우선 Gun.cpp에 있는 PullTrigger() 함수로 돌아가자.여기서 FCollisionQueryParams Params를 선언하고, 해당 Params를 AddIngoredActor 함수를 통해 총과 총의 주인인 캐릭터가 무시되도록 해주자.그리고 해당 Parmas를 LineTraceSingleByChannel에 할당해주면 간단하게 해결이 가능하다. 이제 다른 문제가 남아있는데, 바로 캐릭터가 죽었음에도 불구하고 총을 쏘고 또 캡슐 컴포넌트 또한 남아있다는 것이다.이를 위해 ShooterCharacter 클래스의 TakeDamage 함수로 돌아가자.해당 함수에서 만..

C++에서 BTServices이번에는 행동 트리의 새로운 개념인 서비스에 대해 알아본다.기존에 AIController의 Tick 함수에 구현했던 내용을 서비스를 통해 구현하게 된다.(플레이어 위치, 플레이어 마지막 위치 등)Tick은 매프레임마다 탐색을 하므로 대신 서비스 기능을 사용하여 일정 구간마다 탐색하도록 하게 된다. 우선 행동 트리에서 서비스를 생성해보자.우리가 생성할 기능은 AI가 플레이어 방향을 따라오도록 Default Focus 기능이다. 해당 기능을 통해 기존에는 무조건 앞에만 바라보던 AI가 플레이어 위치에 따라 자연스럽게 방향을 따라오게 된다. 이제 이러한 서비스를 Vscode에서 직접 만들어보자.이를 위해 C++ 클래스를 생성해주는데, 우리는 블랙보드 키 값을 통해 설정할 것 이므로..

폰(Pawn)을 사용하는 BTTask이번에는 AI 시야에 플레이어가 들어오면 AI가 사격을 하도록 기능을 추가해보자.이에 앞서 기존 시야에 들었을 시 플레이어 위치까지 오는 범위를 늘려주자.해당 범위가 너무 좁으면 AI가 총을 플레이어와 너무 가까운 위치에서 사격을 하게 되므로 수정해주는 것이 좋다. 그리고 추가적으로 Observe Blackboard Value 값도 활성화 해주자.해당 기능을 활성화 하지 않았을 시 AI가 플레이어를 따라올 때 자연스럽게 계속 따라오는 것이 아니라 우선 플레이어 위치까지 이동 후에 다시 변경된 플레이어 위치로 이동한다.우리는 자연스럽게 계속 업데이트된 플레이어 위치로 따라오는 것을 원하기에 해당 값을 활성화 해주자. 이제 쏘는 기능을 추가하기 위해 또 새롭게 C++ 클래..

BTTasks 실행하기이제 Task 기능을 직접 실행해보자.현재 우리가 필요한 기능은 선택된 블랙보드 키 값을 지우는 것이다. 우선 베이스 클래스에 어떤 내용이 존재하는지 알아보자.Blackboardbase 헤더에서 UBTTaskNode를 선택하고 F12를 누르면 해당 내용을 볼 수 있다.그럼 상단에 다음과 같은 함수들을 볼 수 있다. 4개를 순서대로 간단히 살펴보면,ExecuteTask가 Task를 실행하는 것이고, AbortTask는 Task 중단, TickTask는 매틱마다 Task 실행, Onmessage는 Task에 메시지를 보낼 때 사용된다.우리가 주로 봐야할 것은 위 3가지 함수이며, 여기서 사용하게 될 것은 단순 실행하는 ExcuteTask가 된다. 이어서 CPP에 작성해주자. #incl..

C++로 커스텀 BTTasks 구성하기이제 행동 트리에 더 많은 기능을 구성해보록 하자.이에 앞서 이번 강의에서는 C++로 커스텀 BTTasks 구성하는 것을 해보게 된다. 일단 기존의 마지막 위치를 탐색하는 노드의 이름을 바꿔주고 데코레이터로 LastKnownPlayerLocation을 할당해주자. 다음으로 BTTask 기반의 C++ 클래스를 새로 생성해준다.우리는 블랙보드 키 값을 적극적으로 사용하고 있기 때문에 BTTask_BlackboardBase 기반을 선택해준다. 이제 헤더와 CPP 파일이 생성될 것이다.헤더에 생성자를 통 태스크를 직접 생성해보자. 이렇게 하면 아직 기능은 없지만, 해당 이름을 가진 노드를 행동 트리에서 생성할 수 있게 된다.이제 할당하고 실행해보면 해당 태스크를 무사히 완..

BT 데코레이터 및 셀렉터현재는 간단하게 플레이어에게 왔다가 일정 시간 지나면 원래 위치로 돌아가는 시퀸스를 설정하였다.우리의 목표는 플레이어가 보이면 플레이어 위치로 이동하고, 아니라면 플레이어의 마지막 위치로 이동하는 것이다.이러한 기능을 위해 셀렉터 노드를 사용할 수 있다.셀렉터 노드 아래 위치한 내용은 첫 태스크가 성공할 때까지 실행하게 된다. 그리고 시퀸스의 데코레이터 기능을 통하여 조건을 설정하는 것이 가능하다.우리는 기존의 블랙보드 키를 이용할 것이므로 블랙보드로 설정한다. 아래는 현재 SelfActor가 설정된 상태이다.우리는 플레이어 위치를 찾아야 하므로 플레이어 위치로 설정해주자.그러면 플레이어 위치가 존재한다면 해당 시퀸스를 실행하게 된다. 만약 플레이어 시야에서 사라지면 거기까지 가..

행동 트리 태스크 및 시퀸스이제 AI가 실제로 앞뒤로 이동하도록 만들어보자.이를 위해 행동 트리에서 태스크를 생성해주어야 한다.이번 강의에서는 단순 이동을 테스트 할 것이기 때문에 Move To 태스크를 사용해보자. 이렇게 생성한 태스크는 시퀸스 아래에 위치하게 된다.시퀸스 아래에 할당한 태스크들은 해당 시퀸스 차례가 되면 순서대로 할당된 태스크들을 실행하게 된다. Move To 태스크를 더 자세히 살펴보면 어디로 이동할 것인지 위치 설정이 가능하다.여기서 우리가 전에 만들었던 블랙보드 키를 이용하여 PlayerLocation 지정이 가능하다. 이동 후에 잠깐 멈췄다가 다시 이동하는 것을 원하므로 Wait 태스크도 생성해주자.Wait 태스크 또한 얼마나 멈출 것 인지에 대한 값 할당이 가능하다. 플레이어..

C++로 블랙보드 키 설정하기이제 블랙보드에서 게임플레이의 상태를 설정해서 AI가 그에 따라 행동할 수 있게 설정하는 블랙보드 키를 C++을 통해 직접 설정해보자.우선 블랙보드 창을 보면 다음과 같이 기본 키를 볼 수 있다. 그리고 VScode에서 GetBlackboardComponent() 함수를 통해 블랙보드 키 값을 설정하는 것이 가능하다.해당 함수를 사용하기 위해서는 관련 헤더를 포함시켜주어야 한다.해당 함수를 통해 플레이어의 위치를 벡터값으로 받아와보자. 이제 설정한 키를 새롭게 할당해보자.상단 New Key를 눌러서 할당하며, VScode 상에서 할당한 이름과 타입을 정확히 일치시켜주어야 한다.이후 실행을 시켜보면 해당 키에 다음과 같이 플레이어 위치 좌표가 뜨는 것을 볼 수 있다. 제대로 ..

행동 트리 및 블랙보드언리얼에서 정교한 AI 행동을 위해서는 보통 행동 트리를 생성한다.이에 행동 트리와 여러 가지 변수를 저장하고 AI의 메모리와 비슷한 기능을 하는 블랙 보드도 같이 생성해주자. 이제 행동 트리를 확인해보면 다음과 같다. 우측 디테일 패널에서 생성했던 블랙 보드를 확인할 수 있고, 우측 상단에서 해당 블랙 보드 모드로 전환도 가능하다. 이제 해당 행동 트리와 블랙 보드를 통해서 우리가 기존에 구현했던 AI 기능을 구현하도록 할 것이다.이를 위해 기존에 작성했던 VScode의 내용은 주석처리해놓고, 행동 트리를 위한 변수를 하나 선언해주자. 해당 행동 트리를 실행하는 함수는 RunBehaviorTree이다.실행하기에 앞서 해당 행동 트리가 유효한 지부터 체크를 해주자. 그리고 언리얼로 ..