Make Unreal REAL.
article thumbnail
이득우의 언리얼 C++ 게임 개발의 정석

 

예제 폴더에서 UI_Result 위젯 블루프린트를 프로젝트 폴더에 복사한다.

 

 

UI_Result 위젯 블루프린트도 UI_Menu와 비슷한 구성을 가진다.

 

 

UI_Menu와 UI_Result는 btnReturnToTitle 버튼이 겹치고 여러 기능이 비슷하기 때문에, UI_Menu에서 부모로 지정했던 ABGameplayWidget을 상속한 클래스를 생성해 기존 기능을 이용하면서 남은 기능을 구현할 것이다.

 

지금부터 해야할 것은 결과를 띄우기 위한 점수 표시와 각 버튼의 기능들을 구현해 바인딩하는 것이다.

  • btnReturnToTitle: 타이틀 화면
  • btnRetryGame: 재도전

 

상속 받은 클래스를 생성하기 전에 버튼 이벤트 처리는 그냥 부모 클래스에서 모두 처리하도록 작성한다.

  • UI_Menu와 UI_Result 위젯 블루프린트는 ABPlayerWidget 클래스를 공통 조상으로 갖는다.
  • 해당 이름의 위젯을 찾지 않으면 바인딩하지 않기 때문에 문제는 없다.

 

 

NativeConstruct() 함수에서 버튼 위젯을 가져와 변수에 저장한 후, OnClicked 델리게이트에 함수를 등록해 바인딩한다.

  • AddToViewport() 호출 시, UI 생성이 완료된 후 위젯 초기화 시점에 호출된다.

 

 

플레이어 컨트롤러를 가져와 레벨을 재시작한다.

  • APlayerController::RestartLevel() 함수로 현재 레벨을 재시작할 수 있다.
  • 여기서는 캐스팅을 굳이 하지 않아도 된다.
  • 언리얼 엔진에서 캐스팅은 비용이 비싼 연산이기 때문에 적게 할수록 좋다.

 

 

이제 최종 점수를 표시하는 기능은 상속 받은 새로운 클래스에서 구현하도록 한다.

 

 

마찬가지로 하위 위젯들을 가져오는 부분을 NativeConstruct() 함수에 작성한다.

 

 

헤더를 포함한다.

 

 

최종 결과와 점수를 표시할 하위 위젯들을 가져온다.

 

 

컴파일한 후 UI_Result의 부모 클래스로 지정해준다.

  • ABGameplayResultWidget의 부모가 ABGameplayWidget이고, ABGameplayResultWidget을 UI_Result의 부모로 지정한 것이다.

 

 

결과 UI는 게임이 종료되면 마지막에 1번 띄워진다.

 

여기서는 결과 UI 위젯을 미리 만들어 두었다가 게임 종료 시에 뷰포트에 띄우는 방식으로 구현한다.

 

뷰포트 위젯은 플레이어 컨트롤러에서 관리한다.

 

 

헤더를 포함한다.

 

 

생성자에서 UI_Result 위젯 블루프린트 클래스를 가져온다.

 

 

BeginPlay() 함수에서 위젯을 생성해 변수에 저장한다.

  • 게임 종료 시에 띄울 것이기 때문에 뷰포트에는 추가하지 않는다.

 

 

ShowResultUI() 함수를 통해 결과 UI를 뷰포트에 추가하고 UI 입력 모드로 전환한다.

  • 게임 종료 시에 호출될 것이다.

 

 

UI 관련 기능을 구현했으니 이제 게임이 종료되는 시점을 정해주어야 한다.

  • 하나는 플레이어가 죽었을 때이다.
  • 다른 하나는 미션을 완수했을 때이다.
    테스트를 위해 편의상 2개의 섹션이 COMPLETE 상태가 되면 미션을 완수한 것으로 간주한다.

 

미션 완수 여부는 게임의 상태이므로 게임 스테이트에서 관리하도록 한다.

 

 

생성자에서 기본값을 설정해주고 미션 완수 관련 함수들을 구현한다.

 

 

게임 모드가 게임의 규칙을 관리하고 중요한 게임 데이터에 대해 인증하는 권한을 갖기 때문에, 의미상 게임 모드에서 미션 완수 여부를 판별한다.

 

 

AddScore() 함수에서 점수를 증가시킨 후 미션 완수 여부를 확인한다.

 

미션에 성공했으면 게임 스테이트에 알린 후 월드에 존재하는 모든 폰을 정지시킨다.

  • UWorld::GetPawnIterator() 함수를 통해 월드에 존재하는 폰을 FConstPawnIterator 반복자를 통해 순회할 수 있다.
    (*It)로 역참조 해도 되고, It->Get() 함수를 사용해도 된다.
  • APawn::TurnOff() 함수를 통해 해당 폰을 정지시킬 수 있다.
    이동, 물리, 사운드, 애니메이션 등이 멈춘다.

 

월드에 존재하는 모든 플레이어에게 결과 UI를 띄운다.

  • 현재는 싱글 플레이기 때문에 1개의 플레이어 컨트롤러만 존재한다.
  • UWorld::GetPlayerControllerIterator() 함수를 통해 월드에 존재하는 플레이어 컨트롤러를 FConstPlayerControllerIterator 반복자를 통해 순회할 수 있다.
    마찬가지로 (*It)로 역참조 해도 되고, It->Get() 함수를 사용해도 된다.

 

 

캐릭터 클래스의 상태 머신에서 플레이어가 죽었을 때 레벨을 재시작하던 부분을 결과 UI를 띄우도록 변경한다.

 

 

NativeConstruct() 함수는 AddToViewport() 함수 호출 시에, UI 생성이 완료된 후 위젯을 초기화하는 시점에 호출된다.

 

현재 결과 UI는 게임 종료 시 AddToViewport() 함수가 호출되고 NativeConstruct() 함수에서 게임 스테이트의 최종 결과를 가져와 표시해야 한다.

 

그러기 위해서는 NativeConstruct() 함수가 실행되기 전에 게임 스테이트가 바인딩되어 있어야 한다.

  • 메모리 낭비를 줄이기 위해 TWeakObjectPtr<T> 약 스마트 포인터 타입으로 가져온다.

 

 

헤더를 포함하고 게임 스테이트 바인딩 함수를 구현한다.

 

 

NativeConstruct() 함수에서 위젯이 초기화되는 시점에 최종 결과를 설정하도록 한다.

  • 약 스마트 포인터는 사용 전에 .IsValid() 함수로 유효한지 확인해주어야 한다.
  • 편의상 게임 스테이트를 약 스마트 포인터 타입으로 가져와 바인딩해 사용했지만, GetWorld()->GetGameState()로 바로 가져와 사용해도 된다.

 

 

플레이어 컨트롤러에서 결과 UI를 뷰포트에 추가하기 전에 게임 스테이트를 바인딩해주면 드디어 완성이다.

 

 

드디어 게임을 완성했다.

 

profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그