숫자야구게임 트러블 슈팅
RTTI vs RAII
GameMode의 BeginPlay()에서 현재 접속한 플레이어의 수를 가지고 랜덤숫자를 뽑은 후 해당 숫자로 GameMode에 만들었던 AllPlayersControllers배열에 접근하여 해당 컨트롤러부터 게임 시작하게 하였음void AMyGameModeBase::BeginPlay()
{
Super::BeginPlay();
int RandNum = GetRandomControllerIndex();
AllPlayerControllers[RandNum]->StartTurn();
}
하지만 인덱스 접근 오류가 발생하였고, 게임이 crash 발생하였다
게임시작하면 서버에서만 GameMode와 GameState는 생성되지만, 클라 접속은 없어 아직 PlayerController는 없음
컨트롤러 없는데 0인덱스로 TArray에 접근하니 에러 발생
따라서 PostLogin함수에서 컨트롤러 추가되면 그 때 StartGame()을 호출하도록 변경
그렇다고 컨트롤러 추가될 때마다 호출하면 안 되므로, flag변수 통해 첫 번째 컨트롤러 접속 시에만 호출하도록 설정
게임 도중에 들어온 사람은 참가 못 하고, 채팅은 가능하게 하다가, 게임 끝나고 새 게임 시작하면 그 때 들어오게 하고 싶었음
그래서 StartGame()에서 현재 참가한 플레이어만 저장해놓고, 이 플레이어 사이에서만 턴돌아가도록 설정
게임 끝나고 새롭게 다시 StartGame()불리면 그 때, 플레이어 숫자 다시 측정하고 시작하도록 하여 구현
Notification이라는 공지용 UI에서 PlayerState에 저장된 남은 시간을 읽고, UI에 띄우고 싶었음
그래서 PlayerController에서 위젯을 생성하고, 뷰포트에 추가하였고, 이 UI에의 NativeContstruct()에서 PlayerState를 가져오려 했지만 안 되었음
공부해보니, PlayerState, PlayerController 등 언리얼 엔진의 Framework들은 BeginPlay() 단계에서는 아직 완전히 생성되지 않으므로 서로 의존하면 안 됨
그래서 AMyPlayerController::OnRep_PlayerState() 함수를 이용하였는데, 이 함수는 PlayerState가 클라이언트에 완전히 복제된 이후 한 번 호출됨
그래서 이 함수를 이용하여 PlayerState가 생긴 이후, UI에서 PlayerState의 값을 가져와 화면에 보여주도록 구현하였음
근데 막상 해보니, 1초에 1번꼴로 값이 갱신되었음
알아보니, 각 액터마다 1초당 레플리케이션 될 수 있는 최대치가 정해져있었음
그래서 생성자에서 최대치를 늘려주어 해결
AMyPlayerState::AMyPlayerState()
{
// ... //
SetNetUpdateFrequency(NetUpdateFrequency);
}
RTTI는 runtime type information의 줄임말로, 런타임에서의 객체타입에 대한 정보
typeid() 함수를 통해 const std::type_info& 객체를 반환받게 되는데 이 반환값은 RTTI를 관리하는 객체. 이 반환값에 name()함수를 사용하면 RTTI 정보를 얻을 수 있다.
RTTI는 dynamic_cast에 대표적으로 많이 사용된다. RTTI를 가지고, 런타임에 포인터 변환이 가능한지 확인해줌
Resource Acquisition Is Initialization의 줄임말로, 객체의 생명주기와 데이터 접근시기를 동일시 하라는 디자인 패턴
객체가 생성될 때 메모리 할당 같이 하고, 소멸될 때 메모리 해제도 같이 하기
메모리 누수를 방지할 수 있다
대표적인 예시로는 스마트 포인터가 있으며, 파일 핸들, 소켓, 락 등 모든 자원(resource) 관리에도 적용되는 패턴