あなたの世界を作りなさい
チャット
音声チャット機能の使用
22分
zepeto voice chat プレビュー版パッケージは、ワールド内でのボイスチャットを可能にします。 zepeto voice chatをインストールしてモードを設定する 1\) ウィンドウをインストール → パッケージマネージャー → zepeto voice chat。 この機能は、マルチプレイヤー要素が実装されたワールドで利用可能です。 テストはモバイルテストでのみ利用可能で、エディターテストでは利用できません。 iosポリシーにより、ボイスチャットが有効なワールドでマイクがオンのとき、デバイスの音量はゼロにはなりません。 マイクがオフのとき、デバイスの音量はゼロになります。 2\) 開発中のunityプロジェクト画面の中央メニューにある\[▼]ボタンをクリックします。 表示されるポップアップメニューで\[ワールド設定を開く]ボタンをクリックします。 3\) zepeto voice chatパッケージが正しくインストールされている場合、ボイスチャットモードオプションが追加されます。 4\) ボイスチャットモードでは、希望するモードを設定してください。 基本 デフォルトで提供されるボイスチャット機能を使用します。 スクリプト ボイスチャットapiを実装してボイスチャット機能を使用します。 ランタイムでボイスチャットのルームアクセスの入退室を処理できます。 異なるチームのためにボイスチャットを実装します(例 赤チームのボイスチャットと青チームのボイスチャット) 現在話しているユーザーを検出する 基本モード:ボイスチャット機能の使用 基本モードのボイスチャットがある世界はこのようになります。 ボイスモジュレーション機能を使用して、より楽しいボイスチャットを作成することもできます。 ボイスチャット機能を持つワールドに入ると、ボイスチャットが自動的に有効になります。 👍 zepetoでボイスチャット機能を初めて使用する際、マイクのアクセスに関するポップアップが表示されます。 ボイスチャット機能を使用するには、アクセスを許可する必要があります。 ボイスチャットボタンをタッチすることで使用できます zepetoアプリ3 26 000以上では、ボイスチャットスピーカーアイコンが表示されません。 スピーチアイコンを表示させたい場合は、スクリプトモードに切り替え、自分のコードを書くためのガイドに従ってください。 スクリプトモード voicechat apiの使用 スクリプトモードは、チームによって分けられたチャンネルでのボイスチャットを有効にします。 機能の説明と以下の例を参照して、機能を実装してください。 api 説明 oninitializedevent 音声チャットapiは、初期化イベントでtrueイベントが発生した後に利用可能です。 このイベントがtrueの場合、音声チャットが利用可能であり、falseの場合は音声チャットが利用できません。 enterroom(roomproperty roomproperty) 音声チャットルームに入るための関数 \ 音声チャットルームに正常に入った後、音声チャットボタンが表示されます。 exitroom() 音声チャットルームを離れるための関数 onroomconnectedevent 音声チャットルームに入る状態を確認するためのイベント。 このイベントがtrueの場合、ユーザーは音声チャットルームに入っています。falseの場合、ユーザーは音声チャットルームを離れています。 onspeechdetectedevent\<string, boolean> 音声チャットで現在話しているユーザーを検出するためのイベント。 \ stringは話しているユーザーのuserid \ booleanは発話が始まるとtrue、発話が終了するとfalseになります。 changeteamid(number teamid) 音声チャットルームで使用するteamidを変更するための関数 \ 1以上の整数値にのみ設定できます。 ルームプロパティクラス api 説明 setaudiomode ボイスチャットで使用するオーディオモード \ audiomode omnidirectional 距離に基づく音声減衰のないボイスチャットモード (このモードはzepetoキャラクターがあってもなくても使用できます) \ audiomode directional 距離に基づく音声減衰のあるボイスチャットモード (zepetoキャラクターの位置に基づいて動作するため、シーンにzepetoキャラクターが存在する必要があります) setteamid ボイスチャットで同じteamidを持つユーザー間のボイスチャットを有効にするために使用されるteamid。 \ 整数値1以上に設定することができます チーム特有のボイスチャット実装の例 ここにvoice chat apiを試すためのサンプルコードがあります。 1\) ボタンを追加し、以下の画像のようにテキストをキャンバスにログとして表示して、ボイスチャットチームチャンネルに入ります。ステータスログを表示します。 ボタン button blueteam 青チームボイスチャット入場ボタン button redteam 赤チームボイスチャット入場ボタン button exit ボイスチャット退出ボタン テキスト text log チャットログを表示するテキスト text team 同じボイスチャットチームチャンネルのメンバーリストを表示するテキスト text currentspeaking 現在ボイスチャットで話しているユーザーidを表示するテキスト。 2\) プロジェクトを作成 > 作成 > zepeto > typescript として、voicechattest に名前を変更します。 3\) 以下のようにサンプルスクリプトを書きます。 voicechattest import { button, inputfield, text } from 'unityengine ui'; import { zepetoscriptbehaviour } from 'zepeto script' import { audiomode, roomproperty, voicechatcontroller } from 'zepeto voice chat' export default class voicechattest extends zepetoscriptbehaviour { // declare ui components as public members public blueteambutton button; public redteambutton button; public exitroombutton button; public logtext text; public currentteamidtext text; public currentspeakinguseridstext text; // declare private members to store speaking user ids and team id input field private currentspeakinguserids string\[]; private teamidinputfield inputfield; start() { this currentspeakinguserids = new array(); // add event listeners for button clicks this blueteambutton onclick addlistener(()=>{ this enterblueteam(); }); this redteambutton onclick addlistener(()=>{ this enterredteam(); }); this exitroombutton onclick addlistener(()=>{ this exitvoicechatroom(); }); // add event listeners for voice chat controller voicechatcontroller oninitializedevent addlistener(init => this oninitialized(init)); voicechatcontroller onroomconnectedevent addlistener(connected => this onroomconnected(connected)); voicechatcontroller onspeechdetectedevent addlistener((userid, speechdetected) => this onspeechdetected(userid, speechdetected)); this logtext text = "\[voicechat] voicechattest start"; } // ondestroy method called when the script is destroyed ondestroy() { voicechatcontroller oninitializedevent removealllisteners(); voicechatcontroller onroomconnectedevent removealllisteners(); voicechatcontroller onspeechdetectedevent removealllisteners(); } // method called when the voice chat system is initialized private oninitialized(initialized boolean) { this logtext text = "\[voicechat] oninitialized " + initialized; } // method called when the voice chat room is connected private onroomconnected(connected boolean) { this logtext text = "\[voicechat] onroomconnected " + connected; } // method called when a user's speech is detected or not detected private onspeechdetected(userid string, speechdetected boolean) { this logtext text = "\[voicechat] onspeechdetected " + userid + ", " + speechdetected; if (speechdetected) { this currentspeakinguserids push(userid); } else { let index = this currentspeakinguserids indexof(userid); this currentspeakinguserids splice(index, 1); } let userids = "\[currentspeakinguserids]\n"; for (let i = 0; i < this currentspeakinguserids length; i++) { userids += this currentspeakinguserids\[i]; userids += "\n"; } this currentspeakinguseridstext text = userids; } // method to enter the blue team's voice chat room public enterblueteam(){ this entervoicechatroom(2); } // method to enter the red team's voice chat room public enterredteam(){ this entervoicechatroom(3); } // method to enter a voice chat room based on the given team index private entervoicechatroom(teamindex number) { console log("\[voicechat] entervoicechatroom"); // create a new roomproperty object and set its properties let roomproperty = new roomproperty(); roomproperty setaudiomode(audiomode omnidirectional); roomproperty setteamid(teamindex); voicechatcontroller enterroom(roomproperty); this currentteamidtext text = "teamid " + roomproperty teamid tostring(); } // method to exit the voice chat room public exitvoicechatroom() { this logtext text = "\[voicechat] exitvoicechatroom"; voicechatcontroller exitroom(); } // method to change the team id for the current user public changeteamid() { // get the new team id from the input field and parse it as an integer let teamid = parseint(this teamidinputfield text); this logtext text = "\[voicechat] changeteamid " + teamid; this currentteamidtext text = "teamid " + teamid tostring(); // change the team id in the voice chat system voicechatcontroller changeteamid(teamid); } } コードの説明 スクリプトが実行されると、start()関数内の各ボタンにイベントが登録され、voicechatcontrollerにoninitialized、onroomconnected、onspeechdetectedイベントが登録されます。 青チームボタンまたは赤チームボタンがクリックされると、entervoicechatroom()関数が実行され、ユーザーは指定されたroompropertyを入力することでボイスチャットルームに入ります。例のルームプロパティは以下の通りです。 roomproperty setaudiomode audiomode omnidirectional。オムニディレクショナルオーディオモードは、プレイヤーの位置に関係なく音量が同じになるモードです。対照的に、ディレクショナルモードは3dサウンドモードであり、キャラクターの位置によって音量が異なるため、キャラクターが遠くなるほど音量が小さくなります。 roomproperty setteamid 青チームはチャンネル2、赤チームはチャンネル3。setteamidはボイスチャットのチャンネルのように機能します。チャンネル2に入ったチームはチャンネル2のプレイヤーとしかボイスチャットできず、チャンネル3に入ったチームはチャンネル3のプレイヤーとしかボイスチャットできません。 exitvoicechatroom()は現在のボイスチャットチームチャンネルから退出します。 onspeechdetected()は、現在ボイスチャットを使用しているプレイヤーidをチームチャンネルのログテキストに出力します。 4\) スクリプトを完成させた後、インスペクターでステップ1で作成したボタンとテキストを割り当てます。 5\) qrコードまたはテストリンクを介してモバイルでテストを実行すると、チームに参加ボタンが押されたときにボイスチャットのアクティベーションボタンが作成され、プレイヤーが話すたびにログにどのプレイヤーがボイスチャットにいるかが表示されます。以下の画面に示されています。 ボイスチャットのスピーチバブル画像の表示例 zepetoアプリ3 26 000以降のバージョンでは、ボイスチャットの発話アイコンは表示されません。 発話アイコンを表示させたい場合は、ガイドに従って自分のコードを書く必要があります。 1\) プレイヤーがボイスチャットにいるときにキャラクターの頭上にスピーチバブルを表示するには、スピーチバブル画像を使用するプレハブを作成する必要があります。以下のように使用したいスピーチバブルpng画像をインポートし、そのテクスチャタイプをスプライトに変更します。 2\) プロジェクト > 作成 > プレハブとし、名前をchatbubbleに変更します。 3\) chatbubbleプレハブをダブルクリックしてプレハブ編集モードに入ります。chatbubbleプレハブを選択し、transform > position > y値を0 35に変更します。 4\) プレハブオブジェクト内にキャンバスを作成します。 chatbubbleプレハブをダブルクリックしてプレハブ編集モードに入り、hierarchy > ui > canvasを追加します。 キャンバスのrecttransformコンポーネントの値を以下のように変更します。 posx 0 , posy 0 幅 100, 高さ 100 scalex 0 005, scaley 0 005, scalez 0 005 キャンバスコンポーネントのrendermoveをワールドスペースに変更します。 5\) キャンバス内にスピーチバブル画像を作成します。 hierarchy > ui > imageをキャンバスの子として追加し、chatbubbleimageに名前を変更します。 chatbubbleimageのrecttransformコンポーネントの値を以下のように変更します。 幅 42, 高さ 42 ステップ1でインポートした画像スプライトを、イメージコンポーネントのソース画像として登録します。 👍 ヒント スピーチバブルの画像スプライトをアニメーション化することもできます。 異なるチームのために別々のバブル画像を使用することもできます。 6\) プロジェクト > 作成 > zepeto > typescriptを作成し、voicechatbubblecontrollerに名前を変更します。 7\) 以下のようなサンプルスクリプトを書いてください。 voicechatbubblecontroller import { gameobject, object } from 'unityengine'; import { knowsockets, zepetoplayers } from 'zepeto character controller' import { zepetoscriptbehaviour } from 'zepeto script' import { audiomode, roomproperty, voicechatcontroller } from 'zepeto voice chat'; export default class voicechatbubblecontroller extends zepetoscriptbehaviour { // ボイスチャットバブルプレハブを格納するためのパブリックgameobject変数 public voicechatprefab gameobject; // ユーザーidに関連付けられたgameobjectを格納するためのプライベートマップ private voicebubblemap map\<string, gameobject> = new map\<string, gameobject>(); start() { // ボイスチャットコントローラーのイベントリスナーを追加 voicechatcontroller oninitializedevent addlistener(init => this oninitialized(init)); voicechatcontroller onroomconnectedevent addlistener(connected => this onroomconnected(connected)); voicechatcontroller onspeechdetectedevent addlistener((userid, speechdetected) => this onspeechdetected(userid, speechdetected)); } // ボイスチャットシステムが初期化されたときに呼ばれるメソッド private oninitialized(initialized boolean) { console log("\[voicechat] oninitialized "); this entervoicechatroom(1); } // ボイスチャットルームが接続されたときに呼ばれるメソッド private onroomconnected(connected boolean) { console log("\[voicechat] onroomconnected "); } // 指定されたチームインデックスに基づいてボイスチャットルームに入るメソッド private entervoicechatroom(teamindex number) { console log("\[voicechat] entervoicechatroom"); // 新しいroompropertyオブジェクトを作成し、そのプロパティを設定 let roomproperty = new roomproperty(); roomproperty setaudiomode(audiomode omnidirectional); voicechatcontroller enterroom(roomproperty); } // ユーザーのスピーチが検出されたときまたは検出されなかったときに呼ばれるメソッド private onspeechdetected(userid string, speechdetected boolean) { console log("\[voicechat] onspeechdetected " + userid + ", " + speechdetected); // ユーザーidがボイスバブルマップにない場合、ボイスバブルを作成 if (!this voicebubblemap has(userid)) { this createvoicebubble(userid); } this setvoicebubble(userid, speechdetected); } // 指定されたユーザーidのボイスバブルのアクティブ状態を設定するメソッド private setvoicebubble(userid string, speechdetected boolean) { const chatbubble = this voicebubblemap get(userid); chatbubble setactive(speechdetected); } // 指定されたユーザーidのためのボイスバブルを作成するメソッド private createvoicebubble(userid string) { // ユーザーキャラクターの頭のソケットを取得 const headsocket = zepetoplayers instance getplayerwithuserid(userid) character getsocket(knowsockets head upper); // 頭のソケット位置にボイスチャットバブルプレハブをインスタンス化 const instancebubble = object instantiate(this voicechatprefab, headsocket) as gameobject; // インスタンス化されたバブルをボイスバブルマップに追加 this voicebubblemap set(userid, instancebubble); instancebubble setactive(false); } lateupdate() { // ボイスバブルマップが空かどうかを確認し、空であれば戻る if (this voicebubblemap size === 0) { return; } // ボイスバブルマップを反復処理し、各バブルgameobjectの回転を更新 this voicebubblemap foreach((bubbleobject gameobject) => { // バブルオブジェクトの回転をカメラの親トランスフォームの回転に合わせる bubbleobject transform rotation = zepetoplayers instance zepetocamera cameraparent transform rotation; }); } } コードの説明 スクリプトが実行されると、start()関数内の各ボタンにイベントが登録され、voicechatcontrollerのoninitialized、onroomconnected、onspeechdetectedイベントが登録されます。 oninitialized()の後、プレイヤーがワールドに入るとvoice chatボタンが画面に表示され、ボタンを押すとentervoicechatroom()が実行されてvoice chatルームに入ります。 プレイヤーがvoicechatをアクティブにして話すたびに、onspeechdetected()が実行され、speechdetectedがtrueの場合はbubblechatオブジェクトが有効になり、falseの場合は無効になります。 onspeechdetected()関数が初めてアクティブになると、createvoicebubble()がvoicechatprefab gameobjectをプレイヤーの頭上に浮かせるためにインスタンス化し、 voicebubblemapにマップデータとして登録します。 lateupdate()を使用して、zepetoワールドのcameraparentに合わせて毎フレーム音声チャットバブルの回転を更新します。これにより、スピーチバブルの画像が常にカメラを向くようになります。最初に voicebubblemapが空かどうかを確認し、そうでなければスピーチバブル画像のプレハブの回転を更新します。 8\) スクリプトの記述が完了したら、インスペクタでvoicechatprefabエントリをstep 1で作成したスピーチバブルプレハブとして割り当てます。 9\) qrコードまたはテストリンクを介してモバイルで実行すると、プレイヤーが音声チャットを使用するたびにキャラクターの頭上にスピーチバブル画像が表示されるはずです。 音声変調 ボイスチャットバージョン0 2 1 previewから、スクリプトモードでボイスチャットの声を変調できます。 https //www youtube com/watch?v=yxfpuqypbqk https //www youtube com/watch?v=yxfpuqypbqk apiガイドとサンプルコードを使用して音声変調を試してみてください。 音声タイプ (enum) 値 説明 タイプ00 0 オリジナル タイプ01 1 チップマンク タイプ02 2 おじ タイプ03 3 エコー タイプ04 4 深い声 タイプ05 5 ロボット タイプ06 6 方言 タイプ07 7 メガホン タイプ08 8 獣 タイプ09 9 機械 タイプ10 10 強い流れ タイプ11 11 子供 タイプ12 12 ハリネズミ ここに声の変調のサンプルスクリプトがあります。 import { button } from 'unityengine ui'; import { zepetoscriptbehaviour } from 'zepeto script'; import { roomproperty, voicechatcontroller, voicetype } from 'zepeto voice chat'; export default class voicemodulationmanager extends zepetoscriptbehaviour { // 異なる音声タイプを設定するためのボタン public buttons button\[]; start() { const voicetypes = \[ voicetype type00, voicetype type01, voicetype type05, voicetype type03, ]; for (const \[index, button] of this buttons entries()) { button onclick addlistener(() => { // クリックされたボタンのインデックスに対応する音声タイプを設定 voicechatcontroller setvoicetype(voicetypes\[index]); }); }; // ボイスチャットシステムが初期化されたときに呼ばれるメソッド voicechatcontroller oninitializedevent addlistener( init => { voicechatcontroller enterroom(new roomproperty());; } ); // ボイスチャットルームに接続されたときに呼ばれるメソッド voicechatcontroller onroomconnectedevent addlistener( connected => { // 初期音声タイプを設定し、ループバックを有効にする voicechatcontroller setvoicetype(voicetypes\[0]); voicechatcontroller enableloopback(true); } ); } // ボイスチャットルームを退出するためのメソッド ondestroy() { voicechatcontroller oninitializedevent removealllisteners(); voicechatcontroller onroomconnectedevent removealllisteners(); } } コードの説明: 各ボタンに異なる音声変調タイプを設定するためのonclickリスナーを追加します。 同じインデックスの要素が ボタン 配列と 音声タイプ 配列が一致します。 ワールドに入ると、 voicechatcontroller が初期化され、ルーム接続が自動的に確立されます。 初期の音声変調タイプは type00 に設定され、ループバックが有効になり、自分の声を聞くことができます。 呼び出しのために注意してください、 setvoicetype と enableloopback には、ルーム接続が必要です。したがって、初期設定は onroomconnectedevent のリスナー内で処理されます。 ローカルプレイヤーの音声再生位置を変更する ローカルプレイヤーのボイスチャット位置を変更するには、 voicechatcontroller setlocalplayertransform() を使用します。 これを使用すると、ボイスチャットで話すときに特定の空間やオブジェクトの位置に設定することで、さまざまなシナリオを作成できます。 📘 ヒント ボイスチャットのトランスフォームは、ローカルプレイヤーのzepetoキャラクターのトランスフォームにリンクしています。 したがって、ローカルプレイヤーのzepetoキャラクターがワールド内に作成されていない場合、あなたの声は伝達されない可能性があります。 この場合、現在のシーン内で音声再生位置を設定することでボイスチャットを使用できます。 setlocalplayertransform() api 説明 public static setlocalplayertransform($transform unityengine transform)\ void ローカルプレイヤーの音声再生位置を変更するための関数 ❗️ 注意 setlocalplayertransform() は、ボイスチャットが初期化された後に、 voicechatcontroller oninitializedevent(true) を呼び出す必要があります。 1\) 以下は、音声位置変更機能のサンプルスクリプトです。 voicetransformsample import { gameobject, transform, vector3 } from 'unityengine'; import { button } from 'unityengine ui'; import { zepetoscriptbehaviour } from 'zepeto script'; import { audiomode, roomproperty, voicechatcontroller } from 'zepeto voice chat'; export default class voicetransformsample extends zepetoscriptbehaviour { // 音声変換を近くに設定するボタン public buttonclosertransform button; // 音声変換を遠くに設定するボタン public buttonfarthertransform button; // 音声位置の変換 private voicetransform transform; start() { // 新しいgameobjectを作成し、音声変換オブジェクトを格納するための変換を割り当てる const voicetransformobject = new gameobject; this voicetransform = voicetransformobject transform; // 音声チャットシステムが初期化されたときに呼び出されるメソッド voicechatcontroller oninitializedevent addlistener( init => { let roomproperty = new roomproperty(); // 音声モードを方向性3d空間音声に設定 roomproperty setaudiomode(audiomode directional); voicechatcontroller enterroom(roomproperty); // ローカルプレイヤーの音声のための音声チャット変換を設定 voicechatcontroller setlocalplayertransform(this voicetransform); } ); // 'buttonclosetransform'がクリックされたときに音声変換位置を(0,0,0)に設定 this buttonclosertransform onclick addlistener(()=>{ this voicetransform position = vector3 zero; }) // 'buttonfartransform'がクリックされたときに音声変換位置を遠くの点に設定 this buttonfarthertransform onclick addlistener(()=>{ this voicetransform position = new vector3(0,0, 10); }) } // 音声チャットルームを退出するためのメソッド ondestroy() { voicechatcontroller oninitializedevent removealllisteners(); voicechatcontroller onroomconnectedevent removealllisteners(); } } コードの説明 シーンが始まるとき、 start() 関数内にvoicetransformobjectというゲームオブジェクトを作成し、voicetransformにtransformを登録します。 ボイスチャットが oninitialized リスナーが呼び出されるとき、次の設定を適用してください: ボイスチャットを3d空間オーディオモードに設定します。 setaudiomode(audiomode directional) ローカルプレイヤーのボイスチャット位置をvoicetransformに設定します。 voicechatcontroller setlocalplayertransform() buttonclosertransformは、ボタンがクリックされたときにvoicetransformの位置を原点(0, 0, 0)に設定します。 buttonfarthertransformは、ボタンがクリックされたときにvoicetransformの位置を(10, 0, 0)に設定します。 2\) シーン内のcanvasにボタンを登録し、voicetransformsampleコンポーネントのbuttonclosertransformとbuttonfarthertransformに接続します。 3\) qrコードまたはテストリンクを使用してモバイルフォンで実行すると、次のことを確認できます。 クローザーボタンを押すと、あなたの声は他の人に近く聞こえます。 ファーザーボタンを押すと、あなたの声は他の人から遠く聞こえます。 https //www youtube com/watch?v=y pj4rcshts https //www youtube com/watch?v=y pj4rcshts