聊天系统概述
PlayNANOO 聊天系统提供基于实时 WebSocket 的聊天功能。本文档介绍聊天系统的整体结构和使用方法。
系统构成
聊天系统由 3 个核心类组成。
| 类 | 职责 |
|---|---|
| ChatManager | 单例管理器,管理聊天服务器连接和 API 调用 |
| ChatClient | 处理 WebSocket 连接和消息收发的核心类 |
| ChatModels | 定义数据模型和事件监听器接口 |
必须实现说明
以上 3 个类是必须实现的类,可以根据用户的项目结构自由修改。
必须实现的要素:
- 实现
IChatListener接口的所有回调方法 - 在 Update() 中定期调用
ChatClient.Service()方法(接收消息所必需) - 调用 WebSocket 连接的服务器列表 API(
PUT /chat/v20211101/server) - 实现 HMAC-SHA256 哈希认证逻辑
运作流程
1. ChatManager.Connect() 호출
↓
2. 서버 목록 API 요청 (PUT /chat/v20211101/server)
↓
3. 서버 목록 수신 후 랜덤 서버 선택
↓
4. ChatClient가 WebSocket 연결 수행
↓
5. 연결 성공 시 IChatListener.OnConnected() 호출
↓
6. 채널 구독 및 메시지 송수신
第 1 步:实现监听器
要接收聊天事件,需要实现 IChatListener 接口。
public class MyChatHandler : MonoBehaviour, IChatListener
{
public void OnConnected()
{
// 서버 연결 성공
Debug.Log("채팅 서버에 연결되었습니다.");
}
public void OnDisconnected()
{
// 서버 연결 해제
Debug.Log("채팅 서버와 연결이 해제되었습니다.");
}
public void OnError(string code, string message)
{
// 오류 발생
Debug.LogError($"오류: [{code}] {message}");
}
public void OnChannels(ChatChannelInfo[] channels)
{
// 채널 목록 수신
foreach (var ch in channels)
{
Debug.Log($"채널: {ch.channel}, 접속자: {ch.count}명");
}
}
public void OnSubscribed(ChatUserInfo user)
{
// 사용자가 채널에 입장
Debug.Log($"{user.visitorName}님이 입장했습니다.");
}
public void OnUnSubscribed(ChatUserInfo user)
{
// 사용자가 채널에서 퇴장
Debug.Log($"{user.visitorName}님이 퇴장했습니다.");
}
public void OnPublicMessage(ChatUserInfo sender, string message)
{
// 공개 메시지 수신
Debug.Log($"[{sender.visitorName}]: {message}");
}
public void OnPrivateMessage(ChatUserInfo sender, string message)
{
// 귓속말 수신
Debug.Log($"[귓속말][{sender.visitorName}]: {message}");
}
public void OnNotifyMessage(ChatUserInfo sender, string message)
{
// 시스템 알림 수신
Debug.Log($"[시스템]: {message}");
}
public void OnPlayerOnline(ChatPlayerInfo[] players)
{
// 플레이어 온라인 상태 수신
foreach (var p in players)
{
string status = p.online == "Y" ? "온라인" : "오프라인";
Debug.Log($"{p.userUniqueId}: {status}");
}
}
}
第 2 步:连接聊天服务器
调用 ChatManager.Instance.Connect() 连接到聊天服务器。
void Start()
{
// IChatListener를 구현한 객체를 전달
ChatManager.Instance.Connect(this);
}
连接成功后将调用 OnConnected() 回调。
第 3 步:订阅频道
连接后订阅所需的频道。
public void OnConnected()
{
// 글로벌 채널 구독
ChatManager.Instance.Subscribe("global");
// 또는 특정 채널 구독
ChatManager.Instance.Subscribe("room_123");
}
第 4 步:发送消息
发送公开消息
向频道内的所有用户发送消息。
public void SendChatMessage(string text)
{
ChatManager.Instance.SendPublicMessage("global", text);
}
发送私信
仅向特定用户发送消息。
public void SendWhisper(string targetUserId, string text)
{
ChatManager.Instance.SendPrivateMessage(targetUserId, text);
}
第 5 步:其他功能
查询频道列表
ChatManager.Instance.GetChannels();
// 결과는 OnChannels() 콜백으로 수신
取消订阅频道
ChatManager.Instance.Unsubscribe("global");
查询玩家在线状态
string[] userIds = new string[] { "user_001", "user_002", "user_003" };
ChatManager.Instance.GetPlayersOnline(userIds);
// 결과는 OnPlayerOnline() 콜백으로 수신
检查连接状态
if (ChatManager.Instance.IsConnected())
{
Debug.Log("채팅 서버에 연결되어 있습니다.");
}
完整使用示例
using UnityEngine;
public class ChatExample : MonoBehaviour, IChatListener
{
void Start()
{
// 1. 채팅 서버 연결
ChatManager.Instance.Connect(this);
}
// 2. 연결 성공 시 채널 구독
public void OnConnected()
{
Debug.Log("연결 성공!");
ChatManager.Instance.Subscribe("global");
}
// 3. 채널 입장 알림
public void OnSubscribed(ChatUserInfo user)
{
Debug.Log($"{user.visitorName}님이 입장했습니다.");
}
// 4. 메시지 수신
public void OnPublicMessage(ChatUserInfo sender, string message)
{
Debug.Log($"[{sender.visitorName}]: {message}");
}
// 5. 메시지 전송 (UI 버튼에서 호출)
public void OnSendButtonClick()
{
ChatManager.Instance.SendPublicMessage("global", "안녕하세요!");
}
// 기타 콜백 구현
public void OnDisconnected() => Debug.Log("연결 해제됨");
public void OnError(string code, string message) => Debug.LogError($"[{code}] {message}");
public void OnChannels(ChatChannelInfo[] channels) { }
public void OnUnSubscribed(ChatUserInfo user) => Debug.Log($"{user.visitorName}님이 퇴장했습니다.");
public void OnPrivateMessage(ChatUserInfo sender, string message) => Debug.Log($"[귓속말] {message}");
public void OnNotifyMessage(ChatUserInfo sender, string message) => Debug.Log($"[알림] {message}");
public void OnPlayerOnline(ChatPlayerInfo[] players) { }
}
注意事项
在 Update 中调用 Service:ChatManager 的 Update() 中调用 ChatClient.Service(),以便在主线程中处理 WebSocket 回调。如果直接修改 ChatManager,需要保留此部分。
单例模式:ChatManager 以单例模式实现,通过
ChatManager.Instance访问。在场景切换时也会保持。断开连接:应用退出时,ChatManager.OnDestroy() 中会自动断开连接。