- Home /
How do I use network groups correctly?
I have run into some problems using network groups in Unity3D.
You may try the demo at the above link and start two instances, one being the server and one being the client. Then try changing channel in one of them and write something. You'll notice the message arrive at both channels, undesired.
In this demo, I want to create multiple chat channels - sort of like IRC channels. I don't want to send excessive amounts of network information so I want to use groups, to only send to the participants of the current channel. However with my current setup it just won't work.
I have thought about two solutions, however neither of them seem that clean. I was hoping that someone might shed light on a better solution or persuade me enough that it ain't that much of a deal with either of these.
- Keep a list of all NetworkPlayers in a channel and have the server send RPCs to each participant.
- Set up listener groups with SetReceivingEnabled for each player to avoid sending to other groups.
The problem is that I plan on having several thousand groups (for a mud-like game).
- Solution #1 sounds like a simple solution but I don't know if it would cause me problems sending several RPCs manually in terms of overhead. I don't expect more than 20 players in a single channel.
- Solution #2 sounds like a bad plan since I'd have to manage recipiency for several thousands of channels. I'm talking about the order of 64k channels at least.
If there only was such a method like networkView.RPC("OnChat", groupId, message);
...
Finally, the source code. The RPC is at the bottom of the script.
using UnityEngine; using Messages = System.Collections.Generic.List<string>;
public class GroupChat : MonoBehaviour { public Rect position = new Rect(0, 0, 200, 450);
private bool networked;
private string message;
private Messages messages;
private NetworkView channel;
private void Awake()
{
Application.runInBackground = true;
networked = false;
message = string.Empty;
messages = new Messages(10);
channel = gameObject.AddComponent<NetworkView>();
channel.observed = null;
channel.stateSynchronization = NetworkStateSynchronization.Off;
}
private void OnGUI()
{
position.x = Screen.width / 2 - position.width / 2;
position.y = Screen.height / 2 - position.height / 2;
GUILayout.BeginArea(position, "Channel", "window");
if (networked)
{
GUISelectChannelGroup();
GUIComposeMessage();
GUIDisplayMessages();
}
else
{
GUIHostOrConnect();
}
GUILayout.EndArea();
}
private void GUIHostOrConnect()
{
const int port = 25678;
if (GUILayout.Button("Host"))
{
Network.InitializeServer(10, port, false);
networked = true;
}
if (GUILayout.Button("Connect"))
{
Network.Connect("localhost", port);
networked = true;
}
}
// This piece of code should allow the user
// to switch between 6 different channels.
// The intent is that talking in one channel
// only will send messages to the users of
// the same channel.
private void GUISelectChannelGroup()
{
string label = string.Format("Tuned channel # {0}", channel.group);
GUILayout.Label(label);
float group = GUILayout.HorizontalSlider(channel.group, 0, 5);
channel.group = Mathf.RoundToInt(group);
}
private void GUIComposeMessage()
{
message = GUILayout.TextField(message, GUILayout.ExpandWidth(true));
bool sendMsg = Event.current.keyCode == KeyCode.Return;
if (sendMsg && !string.IsNullOrEmpty(message))
{
channel.RPC("OnChat", RPCMode.All, message);
message = string.Empty;
}
}
private void GUIDisplayMessages()
{
foreach (var msg in messages)
{
GUILayout.Label(msg);
}
}
// My problem is that OnChat is called even
// if I am in another group than the sender.
// I don't want to recieve messages if I am
// in another group than the sender.
[RPC]
private void OnChat(string message)
{
if (messages.Count == 10)
{
messages.RemoveAt(0);
}
messages.Add(message);
}
}
Answer by Bunny83 · Apr 19, 2011 at 04:27 AM
As far as i can tell the group id is just for grouping buffered RPCs together to be able to remove them selectively. But i never use/used buffered RPCs because they just cause problems and you have minimal control over them. The only useful reference on groups i've found is the page about NetworkInstantiate.
But beside the groups i would definitely send the messages manually. All messages have to be relayed by the server anyway so you can do this manually. Just add a chanel to your RPC parameters and the server do all the work. Just iterate through your channel list. For such a big system i would also recommend to use a messageID (even for storing the messages in a DB). Most chat programs like skype use an ID (maybe GUID) to identify a certain message. That helps to give feedback to the original sender that this particular message has arrived on the server.
Just a last hint: NetworkViews are "virtually" connected through the NetworkViewID. All NetworkViews with the same ID are "connected". As far as i know SetScope only affects the state synchronisation, but RPCs are always sent. The only way you can restrict them is using a RPCMode or a concrete NetworkPlayer.
So you're saying that if I create a networkView with a specific id for a certain channel, I could use that networkView to send data to that specific game object? Or would it only work with state synchronization? I guess I could make a test on this. That way I could create networkviews dynamically when someone enters a new chat room. The idea is that the player should move through the different areas. Though as a last resort I could manage this on a per-player basis using a list of users for a given channel.
Your answer
Follow this Question
Related Questions
Animation over network using rpcs 0 Answers
Assigning Player Numbers 0 Answers
Player info for objects in Multiplayer 1 Answer
Unity networking tutorial? 6 Answers