1. 程式人生 > >最近使用gvoice的小隊語音 一些坑和感悟《一》

最近使用gvoice的小隊語音 一些坑和感悟《一》

騰訊語音外掛gvoice,基於unity

至於匯入外掛什麼的就不多說,多的是教程,但是詳細的使用教程少的可憐,也是踩了好多坑,才算除錯通.

新建一個語音模組管理器 GVoiceManager,做成單例方便呼叫

    public static GVoiceManager _Instance;
    private IGCloudVoice m_voiceengine; //語音引擎,建議全域性唯一

    
    private bool bHaveJoin; //是否已經加入

    public bool micEnable;//mic是否可用
    private bool micIsOpen;//mic是否開啟
    private bool listenerOpen;//揚聲器
    private string CurrentRoomID;//房間號

    private bool ReConnected;//是否重新連線房間
    private Action TimeEndEvent;//等待結束執行的事件
    private float WaitTime;//需要等待時間

初始化,需要的資訊有APPkey,AppID,openID(openID建議使用者唯一,這裡使用模擬的),註冊一些事件回撥以便監聽

        m_voiceengine = GCloudVoice.GetEngine();
        m_voiceengine.SetAppInfo(GVoiceAppID,GVoiceAppKey, "10000000");
        m_voiceengine.Init();
        m_voiceengine.OnJoinRoomComplete += OnJoinRoomComplete;
        m_voiceengine.OnQuitRoomComplete += OnQuitRoomComplete;

然後關鍵的是加入房間退出房間等操作


    //建立加入語音房間
    private void JoinRoom(string  roomName)
    {
        if (!bHaveJoin)//尚未加入房間
        {
            m_voiceengine.SetMode(GCloudVoiceMode.RealTime);
            Debug.Log("加入的房間號:" + roomName);
            int ret = m_voiceengine.JoinTeamRoom(roomName, 15000);
            if (ret == 8194 || ret == 8193)
            {
                //bHaveJoin = true;
                JoinRoom(roomName);//遞迴一次,嘗試重連
            }
        }
        else
        {
            if (roomName == CurrentRoomID|| string.IsNullOrEmpty(CurrentRoomID))//重複加入
                return;
            else
            {
                if (QuitRoom(CurrentRoomID)!= 0)//加入新房間,先退出
                {
                    Debug.Log("退出失敗");
                    return;
                }
                CurrentRoomID = roomName;
                ReConnected = true;
            }
        }
    }
    //退出語音房間
    private int QuitRoom(string roomname)
    {
        if (micIsOpen)
        {
            m_voiceengine.CloseMic();
        }
        if (listenerOpen)
        {
            m_voiceengine.CloseSpeaker();
        }
        if (bHaveJoin)
        {
            int ret = m_voiceengine.QuitRoom(roomname, 15000);
            Debug.Log("退出房間--" + CurrentRoomID);
            CloseListener();
            CloseMic();
            return ret;
        }
        return -1;
    }

    //加入房間結果的回撥
    private void OnJoinRoomComplete(IGCloudVoice.GCloudVoiceCompleteCode code, string roomName, int memberID)
    {
        Debugger.Log(GetType(), "加入房間結果-->" + code);
        if (code == IGCloudVoice.GCloudVoiceCompleteCode.GV_ON_JOINROOM_SUCC)
        {
            CurrentRoomID = roomName;
            bHaveJoin = true;
            OpenListener();
            OpenMic();
        }else
        {
            CurrentRoomID = "";
            bHaveJoin = false;
        }
    }

    //退出房間結果的回撥
    private void OnQuitRoomComplete(IGCloudVoice.GCloudVoiceCompleteCode code, string roomName, int memberID)
    {
        if (code == IGCloudVoice.GCloudVoiceCompleteCode.GV_ON_QUITROOM_SUCC)
        {
            bHaveJoin = false;//退出後請保證 值為false
            //重連
            if (ReConnected && !string.IsNullOrEmpty(CurrentRoomID))
            {
                Debug.Log("嘗試重連" + CurrentRoomID);
                WaitTime = 1f;
                TimeEndEvent = () =>
                {
                    JoinRoom(CurrentRoomID);
                    ReConnected = false;
                };
            }
            else
            {
                CurrentRoomID = "";
            }
           
        }
        else
        {
            Debug.Log("退出語音房間失敗" + code);
        }
    }
    /// <summary>
    /// 開啟Mic     0是成功,-1是失敗, -2是重複開啟, -3是不可用
    /// </summary>
    /// <returns></returns>
    public void OpenMic()
    {
        if (micIsOpen)
        {
            Debugger.Log(GetType(), "Mic重複開啟");
            return;
        }
        int ret  = m_voiceengine.OpenMic();//如果成功返回0
        if (ret != 0)//失敗
        {
            Debugger.Log(GetType(), "Mic開啟失敗");
        }
        else
        {
            micIsOpen = true;
        }    
}
    /// <summary>
    /// 關閉Mic
    /// </summary>
    /// <returns></returns>
    public void CloseMic()
    {
        if (!micIsOpen)
        {
            Debugger.Log(GetType(), "無需關閉Mic");
            return;
        }
        int ret = m_voiceengine.CloseMic();
        if (ret == 0)
        {
            micIsOpen = false;
            Debugger.Log(GetType(), "Mic關閉成功---" + ret);
        }
        else
        {
            Debugger.Log(GetType(), "mic關閉失敗");
        }
    }
    /// <summary>
    /// 開啟揚聲器
    /// </summary>
    /// <returns></returns>
    public void OpenListener()
    {
        if (listenerOpen)
        {
            Debugger.Log(GetType(), "重複開啟揚聲器");
            return;
        }
        int ret = m_voiceengine.OpenSpeaker();
        if (ret == 0)
        {
            Debugger.Log(GetType(), "揚聲器開啟成功");
            listenerOpen = true;
        }
        else
        {
            Debugger.Log(GetType(), "揚聲器開啟失敗");
        }
    }

注意要在update中呼叫pull函式,相當於update

    private void Update()
    {
        if (m_voiceengine != null)
        {
            m_voiceengine.Poll();

            if (WaitTime > 0)
            {
                WaitTime -= Time.deltaTime;
            }
            else
            {
                WaitTime = 0;
                if(TimeEndEvent !=null)
                {
                    TimeEndEvent.Invoke();
                    TimeEndEvent = null;
                }
            }
        }
    }

    void OnDestroy()
    {
        QuitRoom(CurrentRoomID);
    }
    void OnApplicationPause(bool pauseStatus)
    {
        if (m_voiceengine == null)
        {
            return;
        }

        // 應用暫停時GVoice引擎也暫停,應用重新開始時引擎繼續
        if (pauseStatus)
        {
            m_voiceengine.Pause();
        }
        else
        {
            m_voiceengine.Resume();
        }
    }

  到這裡小隊語音基本完成。一開始以為退房間直接呼叫quitroom就行了,後來發現一隻無法再進其他房間,最後查證,是需要在退出後等一小段時間大概0.幾秒,然後去重新設定語音模式,再加入就ok了,不想設定等待時間就遞迴,直到加入成功,或者失敗的房間回撥,在重試

 

另外關於音量調節的呼叫的是 SetSpeakerLevel

 int state = m_voiceengine.SetSpeakerVolume(volum); 返回值為0成功反之失敗

需要注意的是,Windows平臺的音量和移動端是不一樣的,移動端採用十進位制0-800Windows採用16進位制0-65535

成員說話的監聽

  //註冊成員狀態
    private void RegState()
    {
       Debug.Log("註冊監聽");
            OnMemberVoiceFunc = func;
            m_voiceengine.OnMemberVoice += ShowMemberState;
    }
    private void ShowMemberState(int[] arg1, int count)
    {
        for (int i = 0; i < 2* count; i+=2)
        {
            //Debug.Log(arg1[i] + "語音狀態改--" + arg1 [i+1]);
            //成員說話狀態 (除了自己的)
            if (roomData.MemberInfos.ContainsKey(arg1[i])&&arg1[i].ToString() !=memberID)
            {
                GameObject ob = gridTr.Find(arg1[i].ToString()).gameObject;
                if (ob != null)
                {
                    ob.transform.Find("Mic").gameObject.SetActive(arg1[i + 1] >1);
                }
            }
        }
    }

在退出房間是移除註冊,進入房間註冊即可。 需要注意的是,引數count是指變化的人數,陣列奇數項是成員id,偶數項為對應狀態,一般取 》1 為說話狀態,其他為沉默狀態