Chat
The Chat feature allows players to communicate together in-game with text chat.
The purpose of this feature is to allow players to communicate together in-game with text chat.
Here are some common use cases for the Chat feature:
- Single Player Games: Broaden the metagame with social features to boost retention
- Multiplayer Games: Deepen the core game to increase engagement. See Multiplayer for more info
Here is the main chat-related terms to be aware.
| Name |
Detail |
| Room |
A collection of game players (e.g. chatting about a specific topic) |
| Room Player |
A game player within the room |
| Message |
Text sent from one player to all players within the room |
Chat API
Experimental API
This API is experimental and may change in future versions.
Unlike many Beamable Features, Chat does not require a specific Beamable Feature Prefab to be used. The main entry point to this feature is C# programming.
Players can easily send and receive messages in real-time.
The main API highlights include ChatService.
| Method Name |
Detail |
| Subscribe |
Callback to observe changes |
| CreateRoom |
Create a new room |
| GetMyRooms |
Get list of all current rooms |
| LeaveRoom |
Leave the current room |
| SendMessage |
Send a text message to all room players |
Sending Room Message
| room.SendMessage("Hello World!");
|
Receiving Room Message
| private void OnMessageReceived (Message message)
{
Debug.Log($"Message = {message.content}");
}
|
Group Chat
Players can create groups, interact, and chat with group members in real-time. See Groups for more info.
Filtering Chat Messages
Beamable supports filtering chat messages to help keep the game chat safe.
1
2
3
4
5
6
7
8
9
10
11
12
13 | public async void IsProfanity()
{
string text = "pornography"; // Ex. This string is profane
bool isProfanityText = true;
try
{
var result = await _beamContext.Api.Experimental.ChatService.ProfanityAssert(text);
isProfanityText = false;
} catch{}
Debug.Log($"isProfanityText = {isProfanityText} for {text}");
}
|
Limitations
It's worth noting that chat rooms have no specified limit to their capacity. While the network may be perfectly capable of processing messages from hundreds of users, the game clients will start flooding with messages before it becomes a performance problem.
Code Samples
In this example, the player may create a room and send a chat message.
ChatServiceExample.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 | using System.Collections.Generic;
using System.Threading.Tasks;
using Beamable.Common.Api;
using UnityEngine;
using Beamable.Experimental.Api.Chat;
using UnityEngine.Events;
namespace Beamable.Examples.Labs.ChatService
{
/// <summary>
/// Holds data for use in the <see cref="ChatServiceExampleUI"/>.
/// </summary>
[System.Serializable]
public class ChatServiceExampleData
{
public List<string> RoomNames = new List<string>();
public List<string> RoomPlayers = new List<string>();
public List<string> RoomMessages = new List<string>();
public string RoomToCreateName = "";
public string RoomToLeaveName = "";
public bool IsInRoom = false;
public string MessageToSend = "";
}
[System.Serializable]
public class RefreshedUnityEvent : UnityEvent<ChatServiceExampleData> { }
/// <summary>
/// Demonstrates <see cref="ChatService"/>.
/// </summary>
public class ChatServiceExample : MonoBehaviour
{
// Events ---------------------------------------
[HideInInspector]
public RefreshedUnityEvent OnRefreshed = new RefreshedUnityEvent();
// Fields ---------------------------------------
private ChatView _chatView = null;
private BeamContext _beamContext;
private ChatServiceExampleData _data = new ChatServiceExampleData();
// Unity Methods --------------------------------
protected void Start()
{
Debug.Log("Start()");
SetupBeamable();
}
// Methods --------------------------------------
private async void SetupBeamable()
{
_beamContext = BeamContext.Default;
await _beamContext.OnReady;
Debug.Log($"beamContext.UserId = {_beamContext.UserId}");
// Observe ChatService Changes
_beamContext.Api.Experimental.ChatService.Subscribe(chatView =>
{
_chatView = chatView;
// Clear data when ChatService changes
_data.RoomNames.Clear();
_data.RoomMessages.Clear();
_data.RoomPlayers.Clear();
foreach(RoomHandle room in chatView.roomHandles)
{
room.OnRemoved += Room_OnRemoved;
string roomName = $"{room.Name}";
_data.RoomNames.Add(roomName);
room.Subscribe().Then(_ =>
{
// Clear data (again) when Room changes
_data.RoomMessages.Clear();
_data.RoomPlayers.Clear();
_data.RoomToLeaveName = room.Name;
foreach(var message in room.Messages)
{
string roomMessage = $"{message.gamerTag}: {message.content}";
_data.RoomMessages.Add(roomMessage);
}
foreach(var player in room.Players)
{
string playerName = $"{player}";
_data.RoomPlayers.Add(playerName);
}
Refresh();
});
room.OnMessageReceived += Room_OnMessageReceived;
}
Refresh();
});
}
public async Task<bool> IsProfanity(string text)
{
bool isProfanityText = true;
try
{
var result = await _beamContext.Api.Experimental.ChatService.ProfanityAssert(text);
isProfanityText = false;
} catch{}
return isProfanityText;
}
public async Task<EmptyResponse> SendRoomMessage()
{
string messageToSend = _data.MessageToSend;
bool isProfanity = await IsProfanity(messageToSend);
if (isProfanity)
{
// Disallow (or prompt Player to resubmit)
messageToSend = "Message Not Allowed";
}
foreach(RoomHandle room in _chatView.roomHandles)
{
if (room.Players.Count > 0)
{
await room.SendMessage(messageToSend);
}
}
return new EmptyResponse();
}
public async Task<EmptyResponse> CreateRoom ()
{
string roomName = _data.RoomToCreateName;
bool keepSubscribed = false;
List<long> players = new List<long>{_beamContext.PlayerId};
var result = await _beamContext.Api.Experimental.ChatService.CreateRoom(
roomName, keepSubscribed, players);
Refresh();
return new EmptyResponse();
}
public async Task<EmptyResponse> LeaveRoom()
{
var roomInfos = await _beamContext.Api.Experimental.ChatService.GetMyRooms();
foreach(var roomInfo in roomInfos)
{
var result = await _beamContext.Api.Experimental.ChatService.LeaveRoom(roomInfo.id);
}
Refresh();
return new EmptyResponse();
}
public void Refresh()
{
_data.IsInRoom = _data.RoomPlayers.Count > 0;
// Create new mock message
int messageIndex = _data.RoomMessages.Count;
_data.MessageToSend = $"Hello {messageIndex:000}!";
// Create new mock group name
int groupIndex = _data.RoomNames.Count;
_data.RoomToCreateName = $"Room{groupIndex:000}";
// Create temp name for pretty UI
if (string.IsNullOrEmpty(_data.RoomToLeaveName))
{
_data.RoomToLeaveName = _data.RoomToCreateName;
}
// Log
string refreshLog = $"Refresh() ...\n" +
$"\n * RoomNames.Count = {_data.RoomNames.Count}" +
$"\n * RoomPlayers.Count = {_data.RoomPlayers.Count}" +
$"\n * RoomMessages.Count = {_data.RoomMessages.Count}" +
$"\n * IsInRoom = {_data.IsInRoom}\n\n";
Debug.Log(refreshLog);
// Send relevant data to the UI for rendering
OnRefreshed?.Invoke(_data);
}
// Event Handlers -------------------------------
private void Room_OnMessageReceived(Message message)
{
string roomMessage = $"{message.gamerTag}: {message.content}";
Debug.Log($"Room_OnMessageReceived() roomMessage = {roomMessage}");
_data.RoomMessages.Add(roomMessage);
Refresh();
}
private void Room_OnRemoved()
{
Debug.Log($"Room_OnRemoved");
Refresh();
}
}
}
|