멀티플레이어 게임 개발 1 (캐싱, 바인딩)

김여울·2025년 8월 27일

내일배움캠프

목록 보기
65/139

UPROPERTY(meta = (BindWidget))

// CXChatInput.h

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "CXChatInput.generated.h"

class UEditableTextBox;

/**
 * 
 */
UCLASS()
class CHATX_API UCXChatInput : public UUserWidget
{
	GENERATED_BODY()

public:
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UEditableTextBox> EditableTextBox_ChatInput;
	
};
  • UPROPERTY
    • 언리얼 리플렉션(리플렉션 = 에디터나 블루프린트에서 속성 관리 가능) 시스템에 등록하겠다는 표시
    • 가비지 컬렉션 관리 + 에디터/블루프린트 연동 가능해짐
  • meta = (BindWidget)
    • UMG(언리얼 UI 블루프린트) 위젯에 있는 같은 이름의 위젯과 자동으로 연결해주는 옵션
    • 여기서는 EditableTextBox_ChatInput라는 이름의 UEditableTextBox가 UMG 위젯 블루프린트 안에 있어야 자동 바인딩
    • 이름이 정확히 같아야 작동함 (대소문자 포함)
  • TObjectPtr<UEditableTextBox>
    • UEditableTextBox는 언리얼 엔진 기본 제공 입력 가능한 텍스트 박스 위젯 클래스.
    • TObjectPtr는 스마트 포인터(UE5에서 도입된 새로운 UObject 포인터 타입)
      • UEditableTextBox* 대신 쓰는 최신 안전한 방식
  • EditableTextBox_ChatInput
    • C++ 클래스에서 실제로 참조할 변수 이름
    • UMG 안에서 똑같은 이름의 위젯을 찾아 자동으로 매칭됨

메세지 캐싱

// CXPlayerController.h

...
class CHATX_API ACXPlayerController : public APlayerController
{
	...

public:
	virtual void BeginPlay() override;

	// 채팅 문자열을 설정하는 함수
	void SetChatMessageString(const FString& InChatMessageString);
	
protected:
	...

	// 작성한 채팅 메세지 캐싱
	FString ChatMessageString;
};
  • FString ChatMessageString;
    • 이게 핵심 변수
    • "내가 작성한 채팅 메시지를 잠시 저장(캐싱)" 해두는 용도
  • SetChatMessageString(const FString& InChatMessageString)
    • 외부에서 입력한 문자열을 ChatMessageString에 넣어줌
    • 예를 들어 UMG에서 텍스트 박스에 "안녕"이라고 치면 → 이 함수로 넘겨서 ChatMessageString에 저장
  • 캐싱(Cache) 의미
    • "임시로 보관한다"
    • 입력한 채팅 메시지를 바로 서버로 보내지 않고, 우선 PlayerController에 보관해두는 것
    • 나중에 SendChatToServer() 같은 함수를 호출할 때, 이 ChatMessageString을 읽어서 서버로 보내는 구조일 가능성 있음

채팅 위젯 바인딩하기

// CXChatInput.cpp


#include "UI/CXChatInput.h"

#include "Components/EditableTextBox.h"
#include "Player/CXPlayerController.h"

void UCXChatInput::NativeConstruct()
{
	Super::NativeConstruct();

	// 텍스트 박스의 이벤트들
	// Committed에다가 delegate를 통해서 바인드 시킴
	// 바인드가 되어있지 않다면
	if (EditableTextBox_ChatInput->OnTextCommitted.IsAlreadyBound(this, &ThisClass::OnChatInputTextCommitted) == false)
	{
		EditableTextBox_ChatInput->OnTextCommitted.AddDynamic(this, &ThisClass::OnChatInputTextCommitted);		
	}	
}

// 파괴될 때
void UCXChatInput::NativeDestruct()
{
	Super::NativeDestruct();

	// 연결되어 있다면
	if (EditableTextBox_ChatInput->OnTextCommitted.IsAlreadyBound(this, &ThisClass::OnChatInputTextCommitted) == true)
	{
		// 연결을 끊어라~
		EditableTextBox_ChatInput->OnTextCommitted.RemoveDynamic(this, &ThisClass::OnChatInputTextCommitted);
	}
}

// 텍스트를 제출하면 (Enter or Button)
void UCXChatInput::OnChatInputTextCommitted(const FText& Text, ETextCommit::Type CommitMethod)
{
	if (CommitMethod == ETextCommit::OnEnter)
	{
		// GetOwningPlayer를 통해 컨트롤러를 가져옴 -> 엔터를 친 컴퓨터의 플레이어 컨트롤러가 나옴
		APlayerController* OwningPlayerController = GetOwningPlayer();
		// 유효하다!
		if (IsValid(OwningPlayerController) == true)
		{
			// 캐스트도 성공했다!
			ACXPlayerController* OwningCXPlayerController = Cast<ACXPlayerController>(OwningPlayerController);
			if (IsValid(OwningCXPlayerController) == true)
			{
				// 아까 만들었던 메세지 호출
				OwningCXPlayerController->SetChatMessageString(Text.ToString());
				// WBP에서 만들었던 EditableTextBox는 빈 텍스트를 통해 깔끔하게 밀어줌
				EditableTextBox_ChatInput->SetText(FText());
			}
		}
	}
}

0개의 댓글