Using Photon PUN Interest Groups to Cut Unnecessary Network Traffic in Unity Multiplayer
Learn how Photon PUN Interest Groups let you scope network traffic to relevant players, reducing bandwidth in Unity multiplayer games with a concrete shooter example and practical trade‑offs.
16 Nov 2025, 22:29 UTC

Problem: Unnecessary bandwidth in a crowded Unity multiplayer scene
When many players share the same Unity scene, each client receives position updates, RPCs, and object state changes for every other player, even if those objects are far away or irrelevant to the local view. This extra traffic can waste bandwidth, increase latency, and raise costs, especially on mobile or metered connections.
How Photon PUN Interest Groups filter traffic
Photon PUN (PUN 2) lets you split network traffic into logical channels called Interest Groups. Group 0 is the default and always active; groups 1‑255 are custom. A PhotonView or an RPC can be assigned to a specific group. Clients only receive data for groups they have explicitly subscribed to via SetInterestGroups. Sending and receiving can be toggled per group with SetSendingEnabled and SetReceivingEnabled. By matching group subscriptions to gameplay relevance (e.g., proximity or role), you prevent irrelevant updates from ever leaving the server.
Worked example: a simple shooter
Consider a shooter with three types of data:
- Player position updates – high frequency, only needed for nearby players.
- Weapon fire events – lower frequency, but all players should see them.
- Global chat – infrequent, needed by everyone.
Assign each type to a custom group and configure subscriptions as follows:
// Assign groups to PhotonViews or RPCs
// Position updates (group 1)
photonView.Group = 1;
// Weapon fire (group 2)
photonViewFire.Group = 2;
// Chat (group 3) – typically sent via RPC
photonViewChat.Group = 3;
// Enable sending/receiving for the groups we will use
PhotonNetwork.SetSendingEnabled(1, true);
PhotonNetwork.SetReceivingEnabled(1, true);
PhotonNetwork.SetSendingEnabled(2, true);
PhotonNetwork.SetReceivingEnabled(2, true);
PhotonNetwork.SetSendingEnabled(3, true);
PhotonNetwork.SetReceivingEnabled(3, true);
// Client‑side subscription logic (run once per client, e.g., in Start)
bool[] groupsToSubscribe = { 1, 2, 3 }; // adjust per role/proximity
bool[] enable = { true, true, true };
PhotonNetwork.SetInterestGroups(groupsToSubscribe, enable);
// Example: update position subscription based on distance
void UpdatePositionSubscription()
{
bool[] near = { false, false, false };
bool[] far = { false, false, false };
foreach (var other in PhotonNetwork.PlayerList)
{
if (other == PhotonNetwork.LocalPlayer) continue;
float dist = Vector3.Distance(transform.position, other.GetPosition());
if (dist < 20f) near[0] = true; // subscribe to group 1 for nearby players
else far[0] = true; // keep group 1 enabled but not subscribed
}
// Apply changes only when needed to avoid per‑frame overhead
if (needUpdate) PhotonNetwork.SetInterestGroups(new int[]{1}, new bool[]{near[0]});
}
In this setup, each client receives position updates only for avatars within ~20 m, sees all weapon fire events, and gets chat messages. The PhotonStatsGui shows a noticeable drop in “Bytes Out/In” for position data compared with having all clients subscribed to the default group 0 alone.
Trade‑off and practical limits
Managing group subscriptions adds complexity: you must keep assignments consistent across all clients and update them when players move or change roles. Forgetting to subscribe a client to a group that an object belongs to results in silent data loss. Frequent subscription changes (e.g., every frame) can increase CPU usage and cause temporary reception gaps, so batch updates or use distance‑based thresholds to limit how often you call SetInterestGroups. Additionally, Interest Groups are exclusive to Photon PUN; projects using Photon Fusion or Bolt need a different traffic‑filtering approach.
Actionable checklist
- Identify the logical channels in your game (e.g., position, events, chat).
- Assign each PhotonView or RPC to the appropriate group via
photonView.Group. - Enable sending/receiving for those groups globally with
SetSendingEnabledandSetReceivingEnabled. - Implement a subscription strategy that matches gameplay relevance (proximity, team, role) and call
SetInterestGroupsonly when the set of groups actually changes. - Validate with PhotonStatsGui: compare bandwidth metrics before and after enabling group‑based subscriptions.
- Add debug logs or visual alerts to catch missing subscriptions during development.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.