はじめに
この記事はUnityでボイスチャットを導入し、なおかつチャンネルを分けたい、例えばAチームはAチームの会話のみ話せ、Bチームの会話は入ってこない、というような実装をします。
サンプルとなるプロジェクトです。
https://github.com/konbraphat51/PhotonVoiceChannelSperated
細かい部分は本記事とは異なりますが、本筋はだいたい同じです。
Photon IDを空欄にしていますので、後述するID2種をご自分で調達して登録してください。
Photon Voiceでは古い記事の実装がうまく通用しなくなったケースがいくらか見られ、この記事もいずれ劣化するかもしれません。この記事は2022年8月の成功例としてご認識ください
Photon Voice 2の導入
こちらのアセットストアから導入してください。
もしPhotonやったことのある方がいれば、PUN2も導入しないといけないのでは?と思うかもしれませんが、Photon voice 2にはPUN2も含まれていますためPUN2を混入しないでください。 公式もそう言ってます。
Photonの登録
Photonはサーバーサービスですので、アプリの登録をしないといけません。
Photonのページからユーザー登録、そしてRealtime、Voiceの2つのアプリを登録してください。
Photonの設定
Unity画面上部のWindow->Photon Unity Networking->Highlight Server SettingsからUnity側のPhoton設定にアクセスできます。
App ID PUN
にRealtimeの方のアプリIDを、
App ID Voice
にVoiceの方のアプリIDをコピペ。
Fixed Region
をjpにするのが定番となっています。
今からやること
本格的な実装に入っていきます。
仕組みとしましては、 まず
・PhotonManager
・VoiceManager
・スピーカー
の三つのオブジェクトがあります。
PunManagerは、最初にサーバーへの接続する役割を担います。
VoiceManagerは画面の前のあなたの声を収録し、それをネットワークを通じて他人のスピーカーへ送り届けます。
スピーカーは、実際に受信した音を発します。ここで注意したいのが、最初(実行する前)スピーカーはいません。プレハブという形にして、PhotonにInstantiateしてもらう形になります。
PunManager
空オブジェクトに、下記のスクリプトをはっつけてください。
大筋の流れは@UpAllNightさんの超分かりやすい記事を参考にさせて頂きました。
using UnityEngine;
using System.Collections;
using Photon.Pun;
using Photon.Realtime;
public class PunManager : MonoBehaviourPunCallbacks
{
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
void OnGUI()
{
GUILayout.Label(PhotonNetwork.NetworkClientState.ToString());
}
public override void OnConnectedToMaster()
{
PhotonNetwork.JoinOrCreateRoom("room", new RoomOptions(), TypedLobby.Default);
}
//ルームに入室後に呼び出される
public override void OnJoinedRoom()
{
PhotonNetwork.Instantiate("Speaker", Vector3.zero, Quaternion.identity, 0);
}
}
これのおかげで、まずサーバーに接続され、Speaker(後述)が生成されます。
スピーカーオブジェクト
空オブジェクトに、Speaker
Photon Voice View
をアタッチしてください。するとAudio Souce
も勝手に追加されますが削除しないでください。
下図のような感じで設定していれば大丈夫でしょう。
これをプレハブにし、プレハブ名を「Speaker」にして
Assets -> Photon -> Resourcesに保存してください。
ここの原理はこちらの記事が超分かりやすいです。
VoiceManager
空オブジェクトに、Photon Voice NetWork
Recorder
コンポーネントをアタッチしてください。
こんな感じに設定してみてください。画像はPlayerプレハブになっていますが、Speaker Prefabには先ほど作ったスピーカーをアタッチしてください。
ちなみに筆者はTransmit Enableにチェックを付けていなくて詰んでいました。
第一弾(ルーム分けなし)、完成
これでまず、第一弾完成です。試しにビルドして二つ同時に実行すると、自分のマイクの音が返ってくることがわかると思います。
チャンネル分け機能の実装
所属チームなどによってチャンネルを分け、チームごとに分けたボイスチャットをするまで、あと一息です。
先ほどのVoiceManagerに下記のスクリプトをアタッチしてみてください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Voice.PUN;
using Photon.Voice.Unity;
public class VoiceTeamSwitch : MonoBehaviour
{
PhotonVoiceNetwork voiceNetwork;
Recorder recorder;
// Start is called before the first frame update
void Start()
{
voiceNetwork = GetComponent<PhotonVoiceNetwork>();
recorder = GetComponent<Recorder>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
byte[] remove = new byte[0];
byte[] add = new byte[] { 1 };
//チャンネル変更部分
voiceNetwork.Client.OpChangeGroups(remove, add);
recorder.InterestGroup = 1;
//チャンネル変更部分ここまで
Debug.Log(1);
}
if (Input.GetKeyDown(KeyCode.W))
{
byte[] remove = new byte[0];
byte[] add = new byte[] { 2 };
voiceNetwork.Client.OpChangeGroups(remove, add);
recorder.InterestGroup = 2;
Debug.Log(2);
}
}
}
上記のコードで、Qキーを押すとチャンネル1に、Wキーを押すとチャンネル2に切り替えられます。
注意点として、デフォルトはチャンネル0ですが、チャンネル0は「全員」に聞こえるようになっています。よって他チャンネルのボイスを聞こえさせたくない場合は、まずチャンネル0から抜けさせる必要があります。
また、
voiceNetwork.Client.OpChangeGroups(remove, add)
は「受信」するチャンネル
recorder.InterestGroup
は「送信」するチャンネル
です。
「送信」は1チャンネルのみですが、「受信」に関しては複数チャンネル可能です。
第一引数は抜けるチャンネルを、第二は参加するチャンネルを指定します。
ここにbyte[0]を指定すると、「全チャンネル」から脱退・参加
nullをしているすると「何もしない」になります。