1. 프로젝트 생성

간단한 온라인 채팅을 구현하는 것이 전부라서 따로 템플릿을 고를 필요가 없다. 그냥 기본으로 선택하고 생성한다.

또한 UI외 다른 기능은 필요가 없으니 아무것도 없는 빈 맵이면 충분하다. 괜히 광원 같은 다른거 넣어서 메모리 자원을 낭비할 이유가 없다.
2. 평소대로 UI를 만들면서 간단한 기능 구현하기


게임모드, 플레이어 컨트롤러 코드를 생성하고 이를 기반으로 하는 블루 프린트를 만든다.

지금쯤이면 월드 세팅에서 뭘 해야 할지 말 안해도 알겠지
public class BaseballGame : ModuleRules
{
public BaseballGame(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput",
"UMG", "Slate", "SlateCore" });
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
UI를 위한 유저 위젯을 만지려면 Build.cs 파일에서 사용할 모듈에 “UMG”를 넣는 것은 습관적으로 가져야 할 행동이다. 이번에는 좀 고오급 기능을 사용할 예정이니 “Slate”, “SlateCore”도 같이 사용한다.
사실 Slate는 에디터용 UI를 만들 때 쓰는 기능인데 이를 게임용으로 개편한 것이 UMG다. 그래서 대부분 UMG만으로 해결이 되지만 일부 특수한 상황에서는 Slate의 기능을 사용할 수도 있다.


UCLASS()
class BASEBALLGAME_API UChatInput : public UUserWidget
{
GENERATED_BODY()
public:
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
private:
//텍스트 박스의 내용 변화
UFUNCTION()
void OnChatInputTextCommitted(const FText& Text, ETextCommit::Type CommitMethod);
//채팅 내용 입력용 텍스트 박스
UPROPERTY(meta = (AllowPrivateAccess = true, BindWidget))
TObjectPtr<class UEditableTextBox> ChatInputBox;
};
유저위젯 C++파일을 만든다. 그리고 그 내용으로 위젯 1개만 넣는다. EdittableTextBox가 필요한데 내용 수정이 가능한 텍스트 박스다.
이 위젯의 기능을 쓰기 위한 전용 함수도 선언한다. 이 함수의 매개변수는 ETextCommit::Type이라는 enum이 있는데 slate에 정의되어 있다.
void UChatInput::NativeConstruct()
{
Super::NativeConstruct();
if (ChatInputBox->OnTextCommitted.IsAlreadyBound(this, &ThisClass::OnChatInputTextCommitted) == false)
{
ChatInputBox->OnTextCommitted.AddDynamic(this, &ThisClass::OnChatInputTextCommitted);
}
}
void UChatInput::NativeDestruct()
{
Super::NativeDestruct();
if (ChatInputBox->OnTextCommitted.IsAlreadyBound(this, &ThisClass::OnChatInputTextCommitted) == true)
{
ChatInputBox->OnTextCommitted.RemoveDynamic(this, &ThisClass::OnChatInputTextCommitted);
}
}
위젯의 시작 함수와 종료 함수인 NativeConstruct와 NativeDestruct에서는 선언한 위젯에 같이 선언한 함수를 등록, 해제하는 내용을 넣는다.
void UChatInput::OnChatInputTextCommitted(const FText& Text, ETextCommit::Type CommitMethod)
{
//엔터 입력에만 반응함
if (CommitMethod == ETextCommit::OnEnter)
{
}
}
같이 선언한 함수에는 엔터키 입력시에만 진입이 가능한 if문이 있다.
UCLASS()
class BASEBALLGAME_API ABaseballPlayerController : public APlayerController
{
GENERATED_BODY()
public:
virtual void BeginPlay() override;
//채팅 입력
void SetChatMessageString(const FString& ChatMessage);
//채팅 출력
void PrintChatMessageString(const FString& ChatMessage);
private:
//채칭 UI 블루프린트
UPROPERTY(EditDefaultsOnly, Category = "UI", meta = (AllowPrivateAccess = true))
TSubclassOf<class UChatInput> ChatInputWidgetClass;
//화면에 생성된 채팅 UI
UPROPERTY()
TObjectPtr<UChatInput> ChatInputWidgetInstance;
//마지막으로 입력된 채팅 매세지
FString PreviousChatMessage;
};
플레이어 컨트롤러에서는 UI를 생성할 준비를 한다. 그와 함께 채팅 입력 및 출력 함수를 선언한다.
void ABaseballPlayerController::BeginPlay()
{
Super::BeginPlay();
//UI 입력만 허용
FInputModeUIOnly InputModeUIOnly;
SetInputMode(InputModeUIOnly);
//채팅 UI 생성
if (IsValid(ChatInputWidgetClass))
{
ChatInputWidgetInstance = CreateWidget<UChatInput>(this, ChatInputWidgetClass);
if (IsValid(ChatInputWidgetInstance))
{
ChatInputWidgetInstance->AddToViewport();
}
}
}
플레이어컨트롤러의 BeginPlay에서 채팅 UI를 생성한다. 이와 함께 UI 외에는 다른 입력이 불필요하기 때문에 UI 입력만 허용하는 기능도 실행한다.
void ABaseballPlayerController::SetChatMessageString(const FString& ChatMessage)
{
PreviousChatMessage = ChatMessage;
}
void ABaseballPlayerController::PrintChatMessageString(const FString& ChatMessage)
{
UKismetSystemLibrary::PrintString(this, ChatMessage, true, true, FLinearColor::Red, 5.0f);
}
채팅 입력 및 출력 함수의 내용을 간단하게만 구현한다.
//엔터 입력에만 반응함
if (CommitMethod == ETextCommit::OnEnter)
{
APlayerController* PlayerController = GetOwningPlayer();
if (IsValid(PlayerController) == true)
{
ABaseballPlayerController* BaseballPlayerController = Cast<ABaseballPlayerController>(PlayerController);
if (IsValid(BaseballPlayerController) == true)
{
//내용 전송하기
BaseballPlayerController->SetChatMessageString(Text.ToString());
ChatInputBox->SetText(FText());
}
}
}
다시 채팅 UI 코드로 돌아와서, 엔터 키 입력시에만 진입이 가능한 if문 안에 플레이어 컨트롤러의 채팅 입력 함수를 실행하는 코드를 작성한다. 그리고 텍스트 박스 안을 비우는 기능을 구현한다.



위젯 블루프린트를 생성한다. 그리고 위젯 블루프린트에서 EditableTextBox를 생성한다. 이 텍스트 박스의 이름은 코드에서 선언한 변수명과 같아야 한다.

화면 아래쪽에 위치하도록 박스의 크기 및 앵커를 조절한다.

크기 조절과 함께 폰트 설정도 한다. 폰트 컬러가 분홍색으로 되어 있길래 검은 색으로 바꿨다.

플레이어 컨트롤러 블루프린트에서 UI 할당을 잊으면 안된다.

일단 실행하면 UI 생성 및 작동은 된다. 텍스트를 출력하는 함수는 실행하는 곳이 없어서 입력 후 엔터를 누르면 사라지기만 한다.
'언리얼엔진 학습 및 과제' 카테고리의 다른 글
| 온라인 채팅 구현하기 (3) (0) | 2025.11.21 |
|---|---|
| 온라인 채팅 구현하기 (2) (0) | 2025.11.20 |
| 팀 프로젝트 슈터 게임 (8) (0) | 2025.11.14 |
| 팀 프로젝트 슈터 게임 (7) (0) | 2025.11.12 |
| 팀 프로젝트 슈터 게임 (6) (1) | 2025.11.11 |