언리얼C++ 기초, 알고리즘 2문제
if (Type* Var = Cast<Type>(Target)) 패턴은 뭘까if 에서 Cast로 값이 맞는지 확인할떄 nullptr이면 밖으로 나간다. 즉 대입된 결과값 자체를 가지고 true/false를 판단한다.
이 방식의 핵심은 변수에 값이 담겼는가가 아니라 nullptr인지 아니면 유효한 주소인지를 따지는 것이다.
유효한 주소일때만 true가 되어 안쪽 코드가 실행된다.
그래서 자꾸if안에서 뭔가를 체크하는 이유는 스마트 포인터 배울때처럼 weak.ptr을 if(locked)일때만 사용 가능하게
했던 메커니즘하고 똑같은것
if의 괄호 안에서만 사용하게 해주고 싶은것이다.
USpartaGameInstance* SGI = Cast<USpartaGameInstance>(GameInstance);
Cast<USpartaGameInstance> -> "내가 지금부터 USpartaGameInstance` 타입으로 이 물건을 분석해볼게.(GameInstance) -> "대상은 바로 이 GameInstance라는 녀석이야."GameInstance의 신분증(StaticClass)를 확인합니다.SGI 변수는 이제 AddScore()를 호출 할 수 있는 권한을 얻게 된다.GameInstance는 게임이 켜질 때 태어나서 게임이 완전히 꺼질 때까지 단 하나만 존재하는 '최상위 관리자'이다.
왜 확인해야할까
직접 UGameInstance라는 클래스를 바닥부터 코딩하지 않은 것은 맞지만, 엔진이 제공하는 UGameInstance를 상속받아
USpartaGameInstance라는 설계도의 본질을 만들었다.
그런데 엔진은 "너의 게임 인스턴스를 줄게"라며 물건을 건네주는데, 그 타입이 항상 가장 기초적인 UGameInstance*이다.
이 기초적인 녀석은 내가 추가한 CurrentScore나 AddScore()같은 기능을 모른다.
객체의 설계도 또는 신분증
Cast(Target)을 할때 엔지은 내부적으로
Target->GetMyID() == USpartaGameInstance::StaticClass() 이렇게 묻는다
Target이 신분증에 적힌 타입이 T::StaticClass()랑 일치하는가?
그리고 왜 if 안에 자꾸 선언하는 걸까?
Cast는 실패하면 nullptr을 뱉는다. if문 안에 선언하면 캐스팅에 성공헀을 때만 이 중괄호 안의 로직을 실행해라
if 문 안으로 제한해서 메모리와 가독성을 잡는게 C++이중욯마
항상 언리얼에서는 자식 클래스를 쓰니까 new대신 형변환 + GetGameInstance() 받기 인듯
GetGameInstance<T>()
위치: 프로그램 전체 (게임 켜질 때~꺼질 때)
특징: 딱 하나만 존재. 레벨이 바뀌어도 데이터가 유지됨. (가장 큰 주머니)
GetWorld()->GetGameState<T>()
위치: 현재 월드(맵) 안
특징: 현재 진행 중인 "판"의 정보(점수, 시간). 맵이 바뀌면 새로 바뀜.
Subsystem
위치: 어디든 붙을 수 있음 (GameInstance용, World용 등)
특징: "기능 단위"로 쪼개진 미니 매니저.
사용법: GetGameInstance()->GetSubsystem() 처럼 가져옴.
그냥 UUserWidget*으로 선언하면 되는데 굳이 TSubclassOf로 쓰는 이유가 궁금했다.
에디터 편의성 -> UUserWidget*으로 선언하면 에디터 디테일 창에서 어떤 블루프린트 위젯을 쓸지 선택 할 수가 없다. 포인터는 "메모리에 떠 있는 놈"을 찾으려 하기 때문이다.
생성 시점 -> 게임이 시작될 때 HUD는 아직 화면에 없다. 존재하지도 않는 주소를 미리 들고 있을 수 느는없으니까 나중에 이걸로 만들거야라는 클래스 정보(설계도)를 TSubclassOf에 담아두는 것이다.
UTextBlock* TextBlock = Cast<TextBlock> <- 여기 뒤에 왜 *가 오지 않는 걸까?
Cast<T>(객체)에서 < > 사이에 들어가는 것은 타입의 이름 그 자체이다. UTextBlock이라는 클래스 타입 안으로 들어가겠다는 ㄷ뜻이다. 그래서 Cast함수가 내부적으로 이미 포인터를 반환하는거로 설계되어 있다.
void ASprataPlayerController::ShowGameHUD(){
if (HUDWidgetInstance)
{
HUDWidgetInstance->RemoveFromParent();
HUDWidgetInstance = nullptr;
}
메뉴 위젯은 화면에서 지우고(RemoveFromParent), 게임 화면에 띄울 위젯(HUDWidgetInstance)을 생성해서 사용자 눈앞(Viewport)에 갖다주는 과정이다.
이때 SetInputMOde(FInputMOdeGameOnly)를 통해 "이제 마우스 클릭이 아니라 캐릭터 조작을 하겠다"고 선언하는 것까지 한 세트.
if (UTextBlock* ScoreText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName((TEXT("Score")))))
블루프린트 위젯(WBP_HUD)을 만들 때 이름을 Time, Score라고 지었 던걸 칭하는 것.
화면에 작성한 Text가 아니라 이름표임. 이름을 다르게 하면 안됨!!