You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Photon Pun Voice问题:同队静音并订阅其他队伍语音频道

Photon Pun/Voice VR语音分组问题排查与修复

需求说明

  • Blue队(同场用户):无法听到队友语音,仅能与Red队(远程用户)语音互通
  • Red队(远程用户):可与队友交流,同时能与Blue队语音互通

当前问题

编写的语音分组代码未生效,怀疑recorder.InterestGroup功能异常,原代码如下:

[ContextMenu("Join Blue Team")]
public void JoinBlueTeam()
{
    var currentTeam = PhotonNetwork.LocalPlayer.GetPhotonTeam();
    if (currentTeam == null)
    {
        PhotonNetwork.LocalPlayer.JoinTeam("Blue");
        ChangeVoiceGroup("Blue");
    }
    else
    {
        if (!string.Equals(currentTeam.Name, "Blue"))
        {
            PhotonNetwork.LocalPlayer.SwitchTeam("Blue");
            ChangeVoiceGroup("Blue");
        }
    }
}

[ContextMenu("Join Red Team")]
public void JoinRedTeam()
{
    var currentTeam = PhotonNetwork.LocalPlayer.GetPhotonTeam();
    if (currentTeam == null)
    {
        PhotonNetwork.LocalPlayer.JoinTeam("Red");
        ChangeVoiceGroup("Red");
    }
    else
    {
        if (!string.Equals(currentTeam.Name, "Red"))
        {
            PhotonNetwork.LocalPlayer.SwitchTeam("Red");
            ChangeVoiceGroup("Red");
        }
    }
}

private void ChangeVoiceGroup(string team)
{
    if (string.Equals(team,"Blue"))
    {
        
        var recorder = FindObjectOfType<Recorder>();
        recorder.InterestGroup = 1;
        byte[] groupsToRemove = new byte[2];
        groupsToRemove[0] = 0; //Here on side team unsubscribe from main voice channel 
        groupsToRemove[1] = 1; //Here on side team unsubscribe from Blue team voice channel that is their voice channel, so they can not hear each other
        byte[] groupsToAdd = new byte[1];
        groupsToAdd[0] = 2; //And here they will only subscribe to the remote team, so they won't be hearing their team mates but gonna be hearing remote voices
        if (!PhotonVoiceNetwork.Instance.Client.OpChangeGroups(groupsToRemove,groupsToAdd))
        {
            Debug.LogError("Couldn't set the voice groups!");
        }
        else
        {
            Debug.Log("Joined On Site Team Voice Channel!");
        }
    }

    if (string.Equals(team,"Red"))
    {
        var recorder = FindObjectOfType<Recorder>();
        recorder.InterestGroup = 2;
        byte[] groupsToRemove = new byte[2];
        groupsToRemove[0] = 0;
        groupsToRemove[1] = 1;
        byte[] groupsToAdd = new byte[2];
        groupsToAdd[0] = 1; //Here remote team will hear the on side team
        groupsToAdd[1] = 2; //Here remote team also will hear their team
        if (!PhotonVoiceNetwork.Instance.Client.OpChangeGroups(groupsToRemove,groupsToAdd))
        {
            Debug.LogError("Couldn't set the voice groups!");
        }
        else
        {
            Debug.Log("Joined Remote Team Voice Channel!");
        }
    } 
}

问题分析

  1. Recorder获取不可靠:FindObjectOfType<Recorder>()可能因组件未激活、场景多实例等情况返回null,直接导致后续逻辑失效。
  2. 订阅组逻辑冗余:Red队代码中移除了未订阅的Group1,属于无效操作;未明确区分语音发送组(recorder.InterestGroup)和语音订阅组(OpChangeGroups管理)的边界。
  3. 缺少错误校验:未判断Recorder是否获取成功,出现问题时无法快速定位根因。

修复后的代码

using Photon.Pun;
using Photon.Realtime;
using Photon.Voice.Unity;
using UnityEngine;

public class TeamVoiceManager : MonoBehaviourPunCallbacks
{
    [ContextMenu("Join Blue Team")]
    public void JoinBlueTeam()
    {
        var currentTeam = PhotonNetwork.LocalPlayer.GetPhotonTeam();
        if (currentTeam == null || !currentTeam.Name.Equals("Blue"))
        {
            PhotonNetwork.LocalPlayer.JoinTeam("Blue");
            ChangeVoiceGroup("Blue");
        }
    }

    [ContextMenu("Join Red Team")]
    public void JoinRedTeam()
    {
        var currentTeam = PhotonNetwork.LocalPlayer.GetPhotonTeam();
        if (currentTeam == null || !currentTeam.Name.Equals("Red"))
        {
            PhotonNetwork.LocalPlayer.JoinTeam("Red");
            ChangeVoiceGroup("Red");
        }
    }

    private void ChangeVoiceGroup(string team)
    {
        // 通过PhotonVoiceNetwork直接获取本地Recorder,避免FindObjectOfType的不确定性
        var recorder = PhotonVoiceNetwork.Instance.LocalRecorder;
        if (recorder == null)
        {
            Debug.LogError("本地Recorder组件未找到,请检查场景配置");
            return;
        }

        if (team == "Blue")
        {
            // Blue队:语音发送到Group1,仅订阅Group2(接收Red队语音)
            recorder.InterestGroup = 1;
            
            byte[] removeGroups = { 0, 1 };
            byte[] addGroups = { 2 };
            
            if (!PhotonVoiceNetwork.Instance.Client.OpChangeGroups(removeGroups, addGroups))
            {
                Debug.LogError("Blue队语音组设置失败");
            }
            else
            {
                Debug.Log("Blue队语音组配置完成:发送到Group1,订阅Group2");
            }
        }
        else if (team == "Red")
        {
            // Red队:语音发送到Group2,订阅Group1(接收Blue队)+Group2(接收队友)
            recorder.InterestGroup = 2;
            
            byte[] removeGroups = { 0 };
            byte[] addGroups = { 1, 2 };
            
            if (!PhotonVoiceNetwork.Instance.Client.OpChangeGroups(removeGroups, addGroups))
            {
                Debug.LogError("Red队语音组设置失败");
            }
            else
            {
                Debug.Log("Red队语音组配置完成:发送到Group2,订阅Group1、Group2");
            }
        }
    }

    // 可选:玩家进入房间时自动初始化语音组(根据需求调整默认队伍)
    public override void OnJoinedRoom()
    {
        // JoinBlueTeam();
    }
}

必做检查项

  • 在Recorder组件的Inspector面板中,勾选Enable Interest Groups选项,确保分组功能激活。
  • 确认PhotonServerSettings的Voice配置中,Interest Groups功能处于启用状态。
  • 测试时通过Photon Console验证语音连接状态,以及玩家的队伍、语音组订阅/发送配置是否正确。

内容的提问来源于stack exchange,提问作者Akin Erkan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:07:55