UnityUnreal Engine 5 SDK 가이드 미리 보기 버전
설치부터 첫 메시지까지, 순서대로 시작하세요.
CasualTalk는 게임에 채팅방과 채팅 번역을 붙여 주는 SDK입니다. 이
문서는 Unity 게임에 CasualTalk를 붙이는 방법을 처음부터 순서대로
설명합니다. 모든 기능은 CasualTalk라는 클래스에 모여
있어서, 코드 어디서든 CasualTalk.함수이름(...)으로
부르면 됩니다.
CasualTalk는 게임에 채팅방과 채팅 번역을 붙여 주는 SDK입니다. 이
문서는 Unreal Engine 5 게임에 CasualTalk 플러그인을 붙이는 방법을
처음부터 순서대로 설명합니다. 모든 기능은
UCasualTalkSubsystem이라는 서브시스템에 모여 있고,
C++과 블루프린트 모두에서 쓸 수 있습니다.
Unity로 만든 게임과 Unreal로 만든 게임도 같은 AppID를 쓰면 같은 방에서 대화할 수 있습니다.
먼저 알아 둘 말
| 말 | 뜻 |
|---|---|
| AppID | 게임마다 하나씩 발급받는 이름표입니다. 서버는 이 값으로 어느 게임의 채팅인지 구분합니다. |
| UserID | 게임 안에서 플레이어를 구분하는 ID입니다. 게임이 이미 쓰고 있는 계정 ID를 그대로 넘기면 됩니다. |
| UserIDX | 서버가 플레이어마다 붙여 주는 숫자 번호입니다. 채팅을 누가 보냈는지 이 번호로 알 수 있습니다. |
| 방(Room) |
채팅을 주고받는 공간입니다. 이름(예:
guild-42)으로 들어가면 되고, 없는 방이면 새로
만들어집니다.
|
| 콜백 | 나중에 결과가 오면 SDK가 대신 불러 주는 함수입니다. 새 채팅이 왔을 때나 서버 응답이 왔을 때 쓰입니다. |
localhost:8080)에
연결되도록 고정되어 있습니다.서버 주소는 WebUrl 옵션으로 바꿀 수 있고, 기본값은
개발 환경 서버(http://localhost:8080)입니다.
게임 등록(AppID 발급)은 아직 관리자 도구 없이 수동으로 진행합니다.
설치
-
SDK 폴더
Assets/CasualTalk를 내 Unity 프로젝트의Assets폴더 아래에 그대로 복사합니다. -
Unity 메뉴 Window → Package Manager에서
com.unity.nuget.newtonsoft-json패키지가 설치되어 있는지 확인합니다. 없으면 설치합니다. 채팅에 추가 정보(메타데이터)를 실을 때 JSON으로 바꾸는 데 씁니다. -
발급받은 AppID를 준비합니다. 연습할 때는 개발용 AppID
casualtalk-dev를 쓰면 됩니다.
-
플러그인 폴더
Plugins/CasualTalk를 내 게임 프로젝트의Plugins폴더 아래에 그대로 복사합니다(폴더가 없으면 만듭니다). UE 5.8 기준이며, 엔진에 기본으로 들어 있는 모듈만 쓰므로 따로 설치할 것은 없습니다. -
C++에서 쓰려면 게임 모듈의
.Build.cs파일을 열고, 의존 모듈 목록에"CasualTalk"를 추가합니다(아래 코드). 블루프린트에서만 쓴다면 이 단계는 건너뜁니다. -
발급받은 AppID를 준비합니다. 연습할 때는 개발용 AppID
casualtalk-dev를 쓰면 됩니다.
// 내게임.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "CasualTalk" });
빠른 시작
아래 스크립트 하나로 연결 → 방 입장 → 채팅 보내기 → 새 채팅 받기까지 해 볼 수 있습니다. 빈 게임 오브젝트에 붙이고 플레이하면 콘솔에 대화가 찍힙니다.
-
await는 서버 응답이 올 때까지 기다렸다가 다음 줄로 넘어갑니다. 기다리는 동안 게임은 멈추지 않습니다.await를 쓰는 함수에는async를 붙입니다. -
요청 함수의 결과는
IsSuccess로 확인합니다.false면ErrorCode에 실패한 이유가 들어 있습니다. -
새 채팅은 기다리지 않아도
Setup때 등록한 함수(HandleNewChat)로 알아서 들어옵니다.
using UnityEngine;
public class ChatSample : MonoBehaviour
{
// 1. 게임이 시작되면 채팅 서버에 연결합니다
private async void Start()
{
CasualTalkSetupOption option = new CasualTalkSetupOption();
option.AppID = "casualtalk-dev"; // 발급받은 게임 ID
option.UserID = "player-1024"; // 게임에서 쓰는 플레이어 ID
option.Mode = CasualTalkMode.Tcp;
option.OnNewChat = HandleNewChat; // 새 채팅이 오면 HandleNewChat 함수가 불립니다
CasualTalkResponse setup = await CasualTalk.Setup(option);
if (setup.IsSuccess == false)
{
Debug.LogError("연결 실패: " + setup.ErrorCode);
return;
}
// 2. 방에 들어갑니다. 없는 방이면 새로 만들어집니다
CasualTalkResponse<SC_JoinRoomAck> join = await CasualTalk.JoinRoom("guild-42");
if (join.IsSuccess == false)
{
Debug.LogError("입장 실패: " + join.ErrorCode);
return;
}
// 내가 들어오기 전에 오간 최근 대화
foreach (DataChat chat in join.Data.Chats)
{
Debug.Log(chat.Chat);
}
// 3. 채팅을 보냅니다
await CasualTalk.ChatRoom("guild-42", "안녕하세요!");
}
// 4. 들어가 있는 방에 새 채팅이 올라올 때마다 불립니다 (내가 보낸 채팅도 옵니다)
private void HandleNewChat(string roomID, DataChat chat)
{
Debug.Log("[" + roomID + "] " + chat.UserIDX + ": " + chat.Chat);
}
// 5. 게임이 끝날 때 연결을 닫습니다
private void OnApplicationQuit()
{
CasualTalk.Close();
}
}
아래 플레이어 컨트롤러 하나로 연결 → 방 입장 → 채팅 보내기 → 새 채팅 받기까지 해 볼 수 있습니다. 게임 모드의 플레이어 컨트롤러로 지정하고 플레이하면 출력 로그에 대화가 찍힙니다.
- 서버에 요청을 보내는 함수는 결과를 바로 돌려주지 않고, 결과가 오면 마지막 인자로 넘긴 콜백을 불러 줍니다. 그래서 다음 단계는 콜백 안에서 이어 갑니다.
-
[this](...) { ... }는 람다(이름 없는 함수)입니다. 이 예제에서는 람다가 하는 일이 우리 클래스의 함수(OnSetup등)를 부르는 것뿐이라, 실제 처리는 그 함수 안에서 합니다. -
결과는
IsSuccess()로 확인합니다.false면ErrorCode에 실패한 이유가 들어 있습니다. - 콜백은 모두 게임 스레드에서 불리므로 안에서 바로 UI나 액터를 바꿔도 됩니다.
#include "CasualTalkSubsystem.h"
#include "GameFramework/PlayerController.h"
#include "ChatPlayerController.generated.h"
UCLASS()
class AChatPlayerController : public APlayerController
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override;
// 서버 응답과 새 채팅을 받을 함수
void OnSetup(const FCasualTalkResponse& Response);
void OnJoinRoom(const TCasualTalkResponse<FSC_JoinRoomAck>& Response);
void HandleNewChat(const FString& RoomID, const FDataChat& Chat);
UPROPERTY()
TObjectPtr<UCasualTalkSubsystem> CasualTalk;
};
#include "ChatPlayerController.h"
void AChatPlayerController::BeginPlay()
{
Super::BeginPlay();
// CasualTalk 기능은 모두 이 서브시스템에 있습니다
CasualTalk = GetGameInstance()->GetSubsystem<UCasualTalkSubsystem>();
// 1. 채팅 서버에 연결합니다
FCasualTalkSetupOption Option;
Option.AppID = TEXT("casualtalk-dev"); // 발급받은 게임 ID
Option.UserID = TEXT("player-1024"); // 게임에서 쓰는 플레이어 ID
Option.Mode = ECasualTalkMode::Tcp;
// 새 채팅이 오면 HandleNewChat 함수를 부르도록 등록합니다
Option.OnNewChat = [this](const FString& RoomID, const FDataChat& Chat)
{
HandleNewChat(RoomID, Chat);
};
// 연결 결과가 오면 OnSetup 함수를 부릅니다
CasualTalk->Setup(Option, [this](const FCasualTalkResponse& Response)
{
OnSetup(Response);
});
}
void AChatPlayerController::OnSetup(const FCasualTalkResponse& Response)
{
if (!Response.IsSuccess())
{
UE_LOG(LogTemp, Error, TEXT("연결 실패"));
return;
}
// 2. 방에 들어갑니다. 없는 방이면 새로 만들어집니다
CasualTalk->JoinRoom(TEXT("guild-42"), [this](const TCasualTalkResponse<FSC_JoinRoomAck>& JoinResponse)
{
OnJoinRoom(JoinResponse);
});
}
void AChatPlayerController::OnJoinRoom(const TCasualTalkResponse<FSC_JoinRoomAck>& Response)
{
if (!Response.IsSuccess())
{
UE_LOG(LogTemp, Error, TEXT("입장 실패"));
return;
}
// 내가 들어오기 전에 오간 최근 대화
for (const FDataChat& Chat : Response.Data.Chats)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *Chat.Chat);
}
// 3. 채팅을 보냅니다. 결과가 필요 없으면 콜백 자리에 nullptr 를 넣습니다
CasualTalk->ChatRoom(TEXT("guild-42"), TEXT("안녕하세요!"), FString(), nullptr);
}
// 4. 들어가 있는 방에 새 채팅이 올라올 때마다 불립니다 (내가 보낸 채팅도 옵니다)
void AChatPlayerController::HandleNewChat(const FString& RoomID, const FDataChat& Chat)
{
UE_LOG(LogTemp, Log, TEXT("[%s] %lld: %s"), *RoomID, Chat.UserIDX, *Chat.Chat);
}
EndPlay에서
CasualTalk->Close()를 부르세요. 닫으면 아직 오지
않은 결과의 콜백은 불리지 않습니다.
Get Game Instance Subsystem 노드로
CasualTalkSubsystem을 가져온 뒤 Setup,
Join Room 같은 노드를 부릅니다. 각 노드의
Callback 핀에 이벤트를 연결하면 결과가
(ErrorCode, Ack)로 들어오고, 새 채팅은
Setup 노드의 On New Chat 핀에 연결한
이벤트로 들어옵니다.
연결 방식
서버와 연결하는 방법은 두 가지이고, Setup 옵션의
Mode로 고릅니다. 어느 쪽을 골라도 쓰는 함수는 똑같고,
두 방식의 플레이어끼리도 같은 방에서 대화할 수 있습니다. 잘
모르겠으면 기본값(Tcp)을 쓰세요.
| 모드 | 동작 | 이럴 때 씁니다 |
|---|---|---|
| CasualTalkMode.TcpECasualTalkMode::Tcp | 채팅 서버와 연결을 계속 열어 두고, 새 채팅이 올라오면 바로 받습니다. 연결이 끊기면 서버가 그 플레이어를 방에서 자동으로 내보냅니다. | PC · 모바일 앱 (기본값) |
| CasualTalkMode.HttpECasualTalkMode::Http |
연결을 열어 두지 않고, PollInterval마다 "새
채팅 있어요?" 하고 웹 서버에 물어봅니다. 그래서 채팅이 조금
늦게 보일 수 있습니다.
|
소켓 연결을 쓸 수 없는 웹 · 일부 플랫폼 |
API
모든 함수는 CasualTalk.함수이름(...)으로 부릅니다.
서버에 요청을 보내는 함수는 await로 결과를 기다리고,
결과는 CasualTalkResponse로 돌아옵니다. IsSuccess가 true면 서버가
성공으로 처리한 것이고, false면
ErrorCode에 이유가 있습니다.
Setup
게임 인증을 하고 채팅 서버에 연결합니다. 다른 함수를 쓰기 전에 가장 먼저 한 번 불러야 합니다. 실패하면 SDK가 상태를 알아서 정리하므로, 다시 불러 재시도할 수 있습니다.
옵션 (CasualTalkSetupOption)
| 속성 | 타입 | 설명 |
|---|---|---|
AppID |
string |
필수. 게임마다 발급받는 ID.
영문·숫자·_·-, 1~32자
|
UserID |
string |
필수. 게임 안의 플레이어 ID, 1~64자. 같은 값으로
접속하면 항상 같은 UserIDX를 받습니다
|
Mode |
CasualTalkMode |
연결 방식. Tcp(기본) 또는
Http (연결 방식)
|
PollInterval |
TimeSpan | Http 모드에서 새 채팅을 물어보는 간격. 기본 250ms이고, 100ms보다 짧게 해도 더 빨라지지 않습니다 |
OnNewChat |
함수 | 새 채팅이 왔을 때 불릴 함수 (Callback) |
연결에 성공하면 CasualTalk.IsInitialized가
true가 되고, 서버가 붙여 준 내 번호를
CasualTalk.UserIDX로 읽을 수 있습니다. 이미 연결된
상태에서 다시 부르면 DuplicateConnection으로
실패합니다.
Callback
새 채팅은 Setup 옵션의 OnNewChat에 넣어
둔 함수로 들어옵니다. 들어가 있는 방에 누가 채팅을 올릴 때마다(내
채팅 포함) 그 함수가 한 번씩 불립니다.
| 인자 | 타입 | 설명 |
|---|---|---|
roomID |
string | 채팅이 올라온 방 |
chat |
DataChat | 올라온 채팅 (DataChat) |
함수는 SDK가 만든 CasualTalk 게임 오브젝트가 매
프레임 메인 스레드에서 불러 줍니다. 그래서 함수 안에서 바로 UI를
바꿔도 됩니다. Close하면 더 이상 불리지 않으므로 따로
해제할 필요는 없습니다.
// Setup 할 때 등록합니다
option.OnNewChat = HandleNewChat;
// 이름과 인자 모양(string, DataChat)만 맞으면 어떤 함수든 됩니다
private void HandleNewChat(string roomID, DataChat chat)
{
Debug.Log(chat.Chat);
}
JoinRoom
방에 들어갑니다. 방을 미리 만들 필요는 없습니다. 이름으로 들어가면
그 이름의 방이 생깁니다. 같은 방 이름이라도 다른 게임(AppID)의
방과는 섞이지 않습니다. 들어간 뒤부터 그 방의 새 채팅이
OnNewChat로 들어옵니다.
결과 (result.Data: SC_JoinRoomAck)
| 필드 | 타입 | 설명 |
|---|---|---|
RoomID |
string | 들어간 방 이름 |
User |
DataUser | 나 (UserIDX) |
Chats |
List<DataChat> | 내가 들어오기 전에 오간 최근 대화 |
Users |
List<DataUser> | 방에 있는 플레이어. Tcp 모드 플레이어만 들어 있습니다 |
CasualTalkResponse<SC_JoinRoomAck> result = await CasualTalk.JoinRoom("guild-42");
if (result.IsSuccess)
{
Debug.Log("최근 대화 " + result.Data.Chats.Count + "개");
}
ChatRoom
방에 채팅을 보냅니다. 보낸 채팅은 나를 포함해 그 방에 있는
모두에게 OnNewChat로 전달됩니다.
metadata는 채팅에 함께 실을 추가 정보입니다(넣지
않아도 됩니다). 닉네임, 아이콘, 아이템 링크처럼 게임이 정한 정보를
넣으면, 받는 쪽은 DataChat.Meta로 꺼내 씁니다. 내용은
JSON 문자열로 바뀌어 그대로 전달되고, SDK와 서버는 안을 들여다보지
않습니다.
Dictionary<string, object> metadata = new Dictionary<string, object>();
metadata.Add("nick", "하늘바람");
metadata.Add("item", 10231);
await CasualTalk.ChatRoom("guild-42", "이 아이템 어때요?", metadata);
한 플레이어가 1초에 30건을 넘게 보내면, 넘친 채팅은
TooManyRequest로 실패합니다.
QuitRoom
방에서 나갑니다. 나간 뒤에는 그 방의 채팅이 더 이상 들어오지 않습니다.
await CasualTalk.QuitRoom("guild-42");
TranslateRoom
받은 채팅 하나를 원하는 언어로 번역합니다. 말풍선 옆 "번역" 버튼에
연결하면 좋습니다. 원문은 서버가 messageID로 찾으므로
채팅 내용을 다시 보낼 필요는 없습니다.
| 인자 | 설명 |
|---|---|
roomID |
채팅이 올라온 방 |
messageID |
번역할 채팅의 DataChat.MessageID |
lang |
번역할 언어: ko(한국어),
en(영어), ja(일본어)
|
CasualTalkResponse<SC_TranslateRoomAck> result = await CasualTalk.TranslateRoom(roomID, chat.MessageID, "ko");
if (result.IsSuccess)
{
Debug.Log("번역: " + result.Data.Text);
}
원문이 이미 요청한 언어면 원문을 그대로 돌려줍니다. 번역 결과는 저장해 두지 않으므로, 같은 채팅을 다시 번역하면 표현이 조금 달라질 수 있습니다.
HistoryRoom
서버에 보관된 이전 채팅을 불러옵니다. 위로 스크롤해서 지난 대화를 더 보여 줄 때 씁니다.
| 인자 | 설명 |
|---|---|
roomID |
방 |
beforeID |
이 DataChat.MessageID보다 오래된 채팅을
가져옵니다. 보통 화면에 있는 가장 오래된 채팅의 ID를
넘깁니다. 비우면 가장 최근부터
|
count |
가져올 개수 (1~100) |
CasualTalkResponse<SC_HistoryRoomAck> result = await CasualTalk.HistoryRoom(roomID, oldestChat.MessageID, 50);
if (result.IsSuccess)
{
// 오래된 순입니다. 화면 위쪽에 이어 붙입니다
foreach (DataChat chat in result.Data.Chats) Debug.Log(chat.Chat);
}
영속성을 쓰기로 등록한 게임에서만 동작합니다. 쓰지 않는 게임은 항상 빈 목록을 받습니다. 방금 올라온 채팅은 보관되기까지 1초쯤 걸리므로, 입장할 때 받은 최근 대화보다 이전 채팅을 불러올 때 씁니다. 보이는 기간(기본 30일)이 지난 채팅은 불러올 수 없습니다 (제한 사항).
EnrollRoom
"하늘바람 님이 들어왔어요" 같은 입장·퇴장 알림을 미리 등록해
둡니다. 등록해 두면 내가 방에 들어가거나 나갈 때 서버가 나 대신 그
방에 이 채팅을 남겨 줍니다. 다른 플레이어에게는 일반 채팅처럼
OnNewChat로 전달됩니다. 다시 부르면 새 내용으로
바뀝니다.
- 입장 알림은
JoinRoom이 성공할 때 남습니다. -
퇴장 알림은
QuitRoom을 부를 때, 그리고 연결이 끊길 때(Tcp) 또는 새 채팅 확인이 멈출 때(Http) 남습니다. - 메시지와 메타데이터가 모두 비어 있으면 남기지 않습니다.
-
Setup직후, 방에 들어가기 전에 한 번 불러 두면 됩니다.
Dictionary<string, object> joinMetadata = new Dictionary<string, object>();
joinMetadata.Add("type", "join");
Dictionary<string, object> quitMetadata = new Dictionary<string, object>();
quitMetadata.Add("type", "quit");
await CasualTalk.EnrollRoom("하늘바람 님이 들어왔어요", joinMetadata, "하늘바람 님이 나갔어요", quitMetadata);
Close
연결을 끊고 SDK 상태를 정리합니다. 게임이 끝날
때(OnApplicationQuit) 불러 주세요. 닫은 뒤에도
Setup을 다시 불러 새로 연결할 수 있습니다.
private void OnApplicationQuit()
{
CasualTalk.Close();
}
API
모든 함수는 UCasualTalkSubsystem에 있습니다. 액터나
위젯에서
GetGameInstance()->GetSubsystem<UCasualTalkSubsystem>()로 가져와 씁니다. 게임 인스턴스마다 연결이 하나라서, 에디터에서
여러 클라이언트로 플레이(PIE)하면 클라이언트마다 따로 접속합니다.
서버에 요청을 보내는 함수는 결과를 받을 콜백을 마지막 인자로
받습니다. 응답이 오면 SDK가 게임 스레드에서 콜백을 한 번 불러
줍니다. 콜백에는
TCasualTalkResponse가 들어오고, IsSuccess()가 true면 서버가
성공으로 처리한 것입니다. 결과가 필요 없으면 콜백 자리에
nullptr를 넣습니다.
- 연결 전에 부르거나 요청을 보내지 못하면, 콜백이 그 자리에서 바로 실패로 불립니다.
-
Close하면 아직 오지 않은 결과의 콜백은 불리지 않습니다.
Setup
게임 인증을 하고 채팅 서버에 연결합니다. 다른 함수를 쓰기 전에
가장 먼저 한 번 불러야 합니다. 결과는
Callback으로 옵니다. 실패하면 SDK가 상태를 알아서
정리하므로, 다시 불러 재시도할 수 있습니다.
옵션 (FCasualTalkSetupOption)
| 속성 | 타입 | 설명 |
|---|---|---|
AppID |
FString |
필수. 게임마다 발급받는 ID.
영문·숫자·_·-, 1~32자
|
UserID |
FString |
필수. 게임 안의 플레이어 ID, 1~64자. 같은 값으로
접속하면 항상 같은 UserIDX를 받습니다
|
Mode |
ECasualTalkMode |
연결 방식. Tcp(기본) 또는
Http (연결 방식)
|
PollInterval |
FTimespan | Http 모드에서 새 채팅을 물어보는 간격. 기본 250ms이고, 100ms보다 짧게 해도 더 빨라지지 않습니다 |
WebUrl |
FString |
CasualTalk 서버 주소. 기본
http://localhost:8080
|
OnNewChat |
함수 |
새 채팅이 왔을 때 불릴 함수 (Callback). C++ 전용이고, 블루프린트는 Setup 노드의
핀으로 넘깁니다
|
연결에 성공하면 서버가 붙여 준 내 번호를
GetUserIDX()로 읽을 수 있습니다(연결 전에는 0). 이미
연결된 상태에서 다시 부르면 콜백이
DuplicateConnection으로 바로 불립니다.
Callback
새 채팅은 Setup 옵션의 OnNewChat에 넣어
둔 함수로 들어옵니다. 들어가 있는 방에 누가 채팅을 올릴 때마다(내
채팅 포함) 그 함수가 한 번씩 불립니다.
| 인자 | 타입 | 설명 |
|---|---|---|
RoomID |
FString | 채팅이 올라온 방 |
Chat |
FDataChat | 올라온 채팅 (FDataChat) |
함수는 게임 스레드에서 불리므로 안에서 바로 UI나 액터를 바꿔도
됩니다. Close하면 더 이상 불리지 않으므로 따로 해제할
필요는 없습니다. 블루프린트에서는 Setup 노드의
On New Chat 핀에 이벤트를 연결합니다.
// Setup 하기 전에 옵션에 넣습니다. 람다 안에서 우리 클래스의 함수를 부릅니다
Option.OnNewChat = [this](const FString& RoomID, const FDataChat& Chat)
{
HandleNewChat(RoomID, Chat);
};
void AChatPlayerController::HandleNewChat(const FString& RoomID, const FDataChat& Chat)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *Chat.Chat);
}
JoinRoom
방에 들어갑니다. 방을 미리 만들 필요는 없습니다. 이름으로 들어가면
그 이름의 방이 생깁니다. 같은 방 이름이라도 다른 게임(AppID)의
방과는 섞이지 않습니다. 들어간 뒤부터 그 방의 새 채팅이
OnNewChat로 들어옵니다.
결과 (Response.Data: FSC_JoinRoomAck)
| 필드 | 타입 | 설명 |
|---|---|---|
RoomID |
FString | 들어간 방 이름 |
User |
FDataUser | 나 (UserIDX) |
Chats |
TArray<FDataChat> | 내가 들어오기 전에 오간 최근 대화 |
Users |
TArray<FDataUser> | 방에 있는 플레이어. Tcp 모드 플레이어만 들어 있습니다 |
CasualTalk->JoinRoom(TEXT("guild-42"), [this](const TCasualTalkResponse<FSC_JoinRoomAck>& Response)
{
if (Response.IsSuccess())
{
UE_LOG(LogTemp, Log, TEXT("최근 대화 %d개"), Response.Data.Chats.Num());
}
});
ChatRoom
방에 채팅을 보냅니다. 보낸 채팅은 나를 포함해 그 방에 있는
모두에게 OnNewChat로 전달됩니다.
Meta는 채팅에 함께 실을 추가 정보입니다(필요 없으면
FString()). 닉네임, 아이콘, 아이템 링크처럼 게임이
정한 정보를 넣으면, 받는 쪽은 FDataChat.Meta로 꺼내
씁니다. SDK와 서버는 안을 들여다보지 않지만, Unity 게임과 함께
쓴다면 JSON 문자열로 맞추세요.
// 문자열 안의 따옴표는 \" 로 씁니다
const FString Meta = TEXT("{\"nick\":\"하늘바람\",\"item\":10231}");
CasualTalk->ChatRoom(TEXT("guild-42"), TEXT("이 아이템 어때요?"), Meta, nullptr);
한 플레이어가 1초에 30건을 넘게 보내면, 넘친 채팅은 콜백의
Response.ErrorCode가 TooManyRequest로
옵니다.
QuitRoom
방에서 나갑니다. 나간 뒤에는 그 방의 채팅이 더 이상 들어오지 않습니다.
CasualTalk->QuitRoom(TEXT("guild-42"), nullptr);
TranslateRoom
받은 채팅 하나를 원하는 언어로 번역합니다. 말풍선 옆 "번역" 버튼에
연결하면 좋습니다. 원문은 서버가 MessageID로 찾으므로
채팅 내용을 다시 보낼 필요는 없습니다.
| 인자 | 설명 |
|---|---|
RoomID |
채팅이 올라온 방 |
MessageID |
번역할 채팅의 FDataChat.MessageID |
Lang |
번역할 언어: ko(한국어),
en(영어), ja(일본어)
|
CasualTalk->TranslateRoom(RoomID, Chat.MessageID, TEXT("ko"), [this](const TCasualTalkResponse<FSC_TranslateRoomAck>& Response)
{
if (Response.IsSuccess())
{
// Response.Data.MessageID 로 어느 채팅의 번역인지 알 수 있습니다
UE_LOG(LogTemp, Log, TEXT("번역: %s"), *Response.Data.Text);
}
});
원문이 이미 요청한 언어면 원문을 그대로 돌려줍니다. 번역 결과는 저장해 두지 않으므로, 같은 채팅을 다시 번역하면 표현이 조금 달라질 수 있습니다.
HistoryRoom
서버에 보관된 이전 채팅을 불러옵니다. 위로 스크롤해서 지난 대화를 더 보여 줄 때 씁니다.
| 인자 | 설명 |
|---|---|
RoomID |
방 |
BeforeID |
이 FDataChat.MessageID보다 오래된 채팅을
가져옵니다. 보통 화면에 있는 가장 오래된 채팅의 ID를
넘깁니다. 비우면 가장 최근부터
|
Count |
가져올 개수 (1~100) |
CasualTalk->HistoryRoom(RoomID, OldestChat.MessageID, 50, [this](const TCasualTalkResponse<FSC_HistoryRoomAck>& Response)
{
if (Response.IsSuccess())
{
// 오래된 순입니다. 화면 위쪽에 이어 붙입니다
for (const FDataChat& Chat : Response.Data.Chats)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *Chat.Chat);
}
}
});
영속성을 쓰기로 등록한 게임에서만 동작합니다. 쓰지 않는 게임은 항상 빈 목록을 받습니다. 방금 올라온 채팅은 보관되기까지 1초쯤 걸리므로, 입장할 때 받은 최근 대화보다 이전 채팅을 불러올 때 씁니다. 보이는 기간(기본 30일)이 지난 채팅은 불러올 수 없습니다 (제한 사항).
EnrollRoom
"하늘바람 님이 들어왔어요" 같은 입장·퇴장 알림을 미리 등록해
둡니다. 등록해 두면 내가 방에 들어가거나 나갈 때 서버가 나 대신 그
방에 이 채팅을 남겨 줍니다. 다른 플레이어에게는 일반 채팅처럼
OnNewChat로 전달됩니다. 다시 부르면 새 내용으로
바뀝니다.
- 입장 알림은
JoinRoom이 성공할 때 남습니다. -
퇴장 알림은
QuitRoom을 부를 때, 그리고 연결이 끊길 때(Tcp) 또는 새 채팅 확인이 멈출 때(Http) 남습니다. - 메시지와 메타데이터가 모두 비어 있으면 남기지 않습니다.
-
Setup성공 직후, 방에 들어가기 전에 한 번 불러 두면 됩니다.
CasualTalk->EnrollRoom(
TEXT("하늘바람 님이 들어왔어요"), TEXT("{\"type\":\"join\"}"),
TEXT("하늘바람 님이 나갔어요"), TEXT("{\"type\":\"quit\"}"),
nullptr);
Close
연결을 끊고 SDK 상태를 정리합니다. 게임이 끝나면(게임 인스턴스가
사라지면) 서브시스템이 알아서 닫으므로 보통은 부를 필요가
없습니다. 로그아웃처럼 게임 도중에 연결을 끊고 싶을 때 부르고,
닫은 뒤에도 Setup을 다시 불러 새로 연결할 수
있습니다. 아직 오지 않은 결과의 콜백은 불리지 않습니다.
데이터 타입
CasualTalkResponse / CasualTalkResponse<T>
요청 함수가 돌려주는 결과입니다. Setup은
CasualTalkResponse를, 나머지 함수는 서버가 보낸
데이터(Data)가 붙은
CasualTalkResponse<T>를 돌려줍니다.
| 멤버 | 타입 | 설명 |
|---|---|---|
IsSuccess |
bool |
성공했으면 true. 먼저 이것부터 확인합니다
|
ErrorCode |
ErrorCode |
실패한 이유 (에러 코드). 성공이면
Success
|
Data |
T |
서버가 보낸 데이터. 서버 응답을 받지 못했으면
null
|
FCasualTalkResponse / TCasualTalkResponse<T>
요청 콜백에 들어오는 결과입니다. Setup 콜백은
FCasualTalkResponse를, 나머지 함수의 콜백은 서버가 보낸
데이터(Data)가 붙은
TCasualTalkResponse<T>를 받습니다.
| 멤버 | 타입 | 설명 |
|---|---|---|
IsSuccess() |
bool |
성공했으면 true. 먼저 이것부터 확인합니다
|
ErrorCode |
ECasualTalkErrorCode |
실패한 이유 (에러 코드). 성공이면
Success
|
Data |
T |
TCasualTalkResponse에만 있습니다. 서버가 보낸
데이터이고, 응답을 받지 못했으면 빈 값입니다
|
DataChatFDataChat
채팅 하나입니다. 새 채팅(OnNewChat)과 입장할 때 받는
최근 대화가 이 모양으로 옵니다.
| 필드 | 타입 | 설명 |
|---|---|---|
UserIDX |
ulongint64 | 보낸 플레이어의 번호. 같은 게임의 같은 플레이어는 항상 같은 값입니다 |
Chat |
stringFString | 채팅 내용 |
MessageID |
stringFString |
채팅마다 붙는 고유 ID. 번역(TranslateRoom)할 때
넘깁니다
|
Meta |
stringFString | 보낸 쪽이 함께 실은 추가 정보(보통 JSON). 없으면 빈 문자열 |
SC_HistoryRoomAckFSC_HistoryRoomAck
불러온 이전 채팅입니다.
| 필드 | 타입 | 설명 |
|---|---|---|
Chats |
List<DataChat>TArray<FDataChat> | 오래된 순. 더 이전 채팅이 없으면 비어 있습니다 |
RoomID |
stringFString | 요청할 때 넘긴 값 그대로 |
SC_TranslateRoomAckFSC_TranslateRoomAck
번역 결과입니다.
| 필드 | 타입 | 설명 |
|---|---|---|
Text |
stringFString | 번역된 문장 |
Lang |
stringFString | 요청한 언어 |
RoomID, MessageID |
stringFString | 요청할 때 넘긴 값 그대로. 어느 채팅의 번역인지 찾을 때 씁니다 |
에러 코드
실패했을 때 ErrorCode에 들어오는 값입니다.
Unity에서는 ErrorCode입니다.Unreal에서는 ECasualTalkErrorCode이고, 값은 Unity
SDK와 같습니다.
| 값 | 이름 | 언제 |
|---|---|---|
| 0 | Failed |
서버가 요청을 거절했거나 처리하다 실패함. 예: 등록되지 않은 AppID, 잘못된 방 이름, 서버 응답을 받지 못함 |
| 1 | Success |
성공 |
| 2 | DuplicateConnection |
이미 연결된 상태에서 Setup을 다시 부름 |
| 3 | NotConnected |
Setup을 부르기 전이거나 Close한
뒤에 다른 함수를 부름
|
| 4 | Timeout |
서버 응답이 정해진 시간 안에 오지 않음Unreal SDK에서는 쓰지 않습니다. 응답을 받지 못하면
Failed로 옵니다
|
| 5 | TooManyRequest |
1초에 30건을 넘게 채팅함 |
제한 사항
| 항목 | 내용 |
|---|---|
| 채팅 속도 | 플레이어 한 명당 1초에 30건까지. Tcp · Http 모두 같습니다 |
| 번역 언어 |
한국어(ko), 영어(en),
일본어(ja)
|
| 방 대화 보관 | 방마다 최근 약 1,000건까지 남습니다. 마지막 채팅 뒤 7일 동안 아무도 말하지 않은 방은 대화가 모두 지워지고, 다음에 들어오면 빈 방으로 보입니다. Http 모드에서 오래 끊겼다 돌아오면 남아 있는 대화부터 받습니다 |
| 이전 채팅 보관 |
영속성을 쓰는 게임만 서버 DB에 보관합니다.
HistoryRoom으로는 게임마다 정한 기간(기본 30일)
안의 채팅만 불러올 수 있습니다
|
| Http 모드 퇴장 | 앱이 갑자기 꺼지면 다른 플레이어에게 퇴장이 바로 보이지 않고 조금 늦게(최대 약 30초) 알려질 수 있습니다 |
| 플레이어 확인 |
CasualTalk는 게임이 보낸 UserID를 그대로
믿습니다. 로그인 같은 플레이어 인증은 게임 쪽에서 먼저 마친
뒤 연결하세요
|