This tutorial enables you to quickly get started integrating voice chat into Unity's TANKS! Networking game application, using the Agora Gaming SDK.
This sample app demonstrates the basic Agora SDK feature:
- Agora.io Developer Account
- Unity 3D 5.5+
The Agora integration for the Unity Tanks demo application, is comprised of one main class, AgoraCanvas, one mute button class, and one logging class LoggerBridge.
- Set up the Tanks Demo Application
- Add Agora UI to the Scene
- Create the Folder Structure and Assets
- Create the AgoraCanvas Class
- Create the MuteButton Class
- Create the LoggerBridge Class
- Link the Classes to the UI Objects
- Add App Settings, Agora SDK, and Run the App
-
Add Unity's TANKS! Networking Demo to your Unity account.
Ensure you are logged into unity, and Clicking on the Add to My Assets button.
Read through the Terms of Service and click on the Accept button to add the project.
Once the project has been added, a confirmation will appear at the top of the screen.
-
Download the Tanks project within the Unity desktop app.
Click Open in Unity to launch Unity.
Ensure the Learn tab is selected, and scroll down to the Tanks project. Click Download to start the download process.
Note: The Download button will change to a loader bar to show download progress.
-
Start the Tanks project in Unity.
When the download is complete, the Start button will appear. Click on Start to load your project.
Note: It may take some time to import all the assets associated with this project.
The Tanks Demo application consists of one Unity scene called _Complete-Game.
Add a Canvas object to the stage.
The Canvas contains the following objects:
| UI Variable | UI object | Description |
|---|---|---|
mShownMessage |
Text object | Welcome message for the user. |
mChannelNameInputField |
Text input box | Text input box for the user to enter the channel name. |
mBtnJoinChannel |
Join Channel UI button | Button to join the channel. |
mBtnLeaveChannel |
Leave Channel UI button | Button to leave the channel. |
MuteButton |
Mute UI button | Button to mute / unmute audio. |
These objects will be linked to the AgoraCanvas class in the Create the AgoraCanvas Class section.
Add a LoggerBridge object to the stage.
This object will be linked to the LoggerBridge class in the Create the AgoraCanvas Class section.
-
Create a folder called
AgoraCanvasin theAssetsfolder in the demo app. This folder will store the custom classes for integrating Agora Voice. -
Create three empty
.csfiles and place them in theAgoraCanvasfolder:- AgoraCanvas.cs
- LoggerBridge.cs
- MuteButton.cs
-
Create an
imagesfolder within theAgoraCanvasfolder, that contain two image files:- btnMute.png
- btnMuteBlue.png
Note: You can use any two images to represent the active / inactive audio mute button.
The next two sections will cover the contents of the AgoraCanvas, MuteButton, and LoggerBridge classes.
The AgoraCanvas class is a subclass of MonoBehaviour. The AgoraCanvas.cs file contains the relevant Agora SDK code for the Unity 3D sample application.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using agora_gaming_rtc;
public class AgoraCanvas : MonoBehaviour
{
...
}The remaining code in this section are contained within the AgoraCanvas class declaration.
- Declare Global Variables
- Create Initialization Methods
- Join / Leave Channel Methods
- Mute / Unmute Audio Method
The AgoraCanvas class has five variables representing the UI objects.
| Variable | Description |
|---|---|
mChannelNameInputField |
Text input field for the channel name. |
mShownMessage |
Welcome message for the user. |
versionText |
Display text for the application version number. |
joinChannel |
Join Channel button. |
leaveChannel |
Leave Channel button. |
muteButton |
Button with a picture of a microphone to mute/unmute audio. |
public InputField mChannelNameInputField;
public Text mShownMessage;
public Text versionText;
public Button joinChannel;
public Button leaveChannel;
public MuteButton muteButton;Declare the mRtcEngine variable, which represents the Agora RTC engine for the application and App ID appId. The appId variable is initialized with the Agora App ID from your Agora Dashboard.
Note: #YOUR APP ID# must be replaced with a valid Agora App ID.
private IRtcEngine mRtcEngine = null;
// PLEASE KEEP THIS App ID IN SAFE PLACE
// Get your own App ID at https://dashboard.agora.io/
// After you entered the App ID, remove ## outside of Your App ID
private string appId = #YOUR APP ID#;The Awake() method is invoked when the application awakens.
Set video sync count QualitySettings.vSyncCount to 0 and the target frame rate Application.targetFrameRate to 30.
void Awake ()
{
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = 30;
}The Start() method initializes the application, Agora engine and UI event listeners.
// Use this for initialization
void Start ()
{
...
}- Add UI Event Listeners and Initialize Agora Engine
- Add Channel Join / Leave Event Listeners
- Add User Event Listeners
- Add Audio Change Event Listeners
- Add Warning and Error Event Listeners
- Add the Statistics Event Listener
- Add Connection Event Listeners
- Configure the Agora RTC Engine
Add click event listeners to the joinChannel and leaveChannel buttons using onClick.AddListener.
joinChannel.onClick.AddListener (JoinChannel);
leaveChannel.onClick.AddListener (LeaveChannel);Initialize the Agora RTC engine mRtcEngine by passing appId into IRtcEngine.GetEngine().
Update the version display text by retrieving the SDK version using IRtcEngine.GetSdkVersion().
mRtcEngine = IRtcEngine.GetEngine (appId);
versionText.GetComponent<Text> ().text ="Version : " + IRtcEngine.GetSdkVersion ();The OnJoinChannelSuccess event listener for mRtcEngine triggers when a user successfully joins a channel.
-
Create a string object
joinSuccessMessagefor the user'suid,channelname, and SDKversionusingstring.Format (). -
Set a debug log using
Debug.Log ()and the text formShownMessage.GetComponent<Text> ()withjoinSuccessMessage. -
Display the mute button using
muteButton.SetHidden()
mRtcEngine.OnJoinChannelSuccess += (string channelName, uint uid, int elapsed) => {
string joinSuccessMessage = string.Format ("joinChannel callback uid: {0}, channel: {1}, version: {2}", uid, channelName, IRtcEngine.GetSdkVersion ());
Debug.Log (joinSuccessMessage);
mShownMessage.GetComponent<Text> ().text = (joinSuccessMessage);
};
muteButton.SetHidden (false);The OnLeaveChannel event listener for mRtcEngine triggers when a user successfully leaves a channel.
-
Create a string object
leaveChannelMessagefor the sessionduration,txlocation,rxlocation,txbitrate, andrxbitrate usingstring.Format (). -
Set a debug log using
Debug.Log ()and the text formShownMessage.GetComponent<Text> ()withleaveChannelMessage. -
Hide the mute button using
muteButton.SetHidden()
mRtcEngine.OnLeaveChannel += (RtcStats stats) => {
string leaveChannelMessage = string.Format ("onLeaveChannel callback duration {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate);
Debug.Log (leaveChannelMessage);
mShownMessage.GetComponent<Text> ().text = (leaveChannelMessage);
muteButton.SetHidden (true);
};The onUserJoined event listener for mRtcEngine triggers when a user joins the channel.
Set a debug log for the user's uid and elapsed time using Debug.Log ().
mRtcEngine.OnUserJoined += (uint uid, int elapsed) => {
string userJoinedMessage = string.Format ("onUserJoined callback uid {0} {1}", uid, elapsed);
Debug.Log (userJoinedMessage);
};The OnUserOffline event listener for mRtcEngine triggers when a user goes offline.
Set a debug log for the user's uid and reason using Debug.Log ().
mRtcEngine.OnUserOffline += (uint uid, USER_OFFLINE_REASON reason) => {
string userOfflineMessage = string.Format ("onUserOffline callback uid {0} {1}", uid, reason);
Debug.Log (userOfflineMessage);
};The OnUserMuted event listener for mRtcEngine triggers when a user mutes their audio.
Set a debug log for the user's uid and muted status using Debug.Log ().
mRtcEngine.OnUserMuted += (uint uid, bool muted) => {
string userMutedMessage = string.Format ("onUserMuted callback uid {0} {1}", uid, muted);
Debug.Log (userMutedMessage);
};The OnVolumeIndication event listener for mRtcEngine triggers when the audio device indicators change.
If the number of speakers is 0 or invalid, set a debug log for the total volume using Debug.Log ().
Iterate through the speakers and set a debug log for the speakerNumber, the speaker's uid, and volume of the speaker using Debug.Log ().
mRtcEngine.OnVolumeIndication += (AudioVolumeInfo[] speakers, int speakerNumber, int totalVolume) => {
if (speakerNumber == 0 || speakers == null) {
Debug.Log (string.Format("onVolumeIndication only local {0}", totalVolume));
}
for (int idx = 0; idx < speakerNumber; idx++) {
string volumeIndicationMessage = string.Format ("{0} onVolumeIndication {1} {2}", speakerNumber, speakers[idx].uid, speakers[idx].volume);
Debug.Log (volumeIndicationMessage);
}
};The OnAudioRouteChanged event listener for mRtcEngine triggers when the audio route changes.
Set a debug log for the route using Debug.Log ().
mRtcEngine.OnAudioRouteChanged += (AUDIO_ROUTE route) => {
string routeMessage = string.Format ("onAudioRouteChanged {0}", route);
Debug.Log (routeMessage);
};The OnWarning event listener for mRtcEngine triggers when a warning occurs in the Agora RTC engine.
Set a debug log for the warn object, warning msg, and warning description using Debug.Log ().
mRtcEngine.OnWarning += (int warn, string msg) => {
string description = IRtcEngine.GetErrorDescription(warn);
string warningMessage = string.Format ("onWarning callback {0} {1} {2}", warn, msg, description);
Debug.Log (warningMessage);
};The OnError event listener for mRtcEngine triggers when an error occurs in the Agora RTC engine.
Set a debug log for the error object, error msg, and error description using Debug.Log ().
mRtcEngine.OnError += (int error, string msg) => {
string description = IRtcEngine.GetErrorDescription(error);
string errorMessage = string.Format ("onError callback {0} {1} {2}", error, msg, description);
Debug.Log (errorMessage);
};The OnRtcStats event listener for mRtcEngine triggers when the statistics change on the Agora RTC engine.
-
Set a debug log for the following statistics:
duration,txBytes,rxBytes,txKBitRate,rxKBitRate,txAudioKBitRate,rxAudioKBitRate,usersusingDebug.Log (). -
Retrieve the length of the mixing file and mixing duration using
mRtcEngine.GetAudioMixingDuration()andmRtcEngine.GetAudioMixingCurrentPosition(). -
Set a debug log of
lengthOfMixingFileandcurrentTsusingDebug.Log ().
mRtcEngine.OnRtcStats += (RtcStats stats) => {
string rtcStatsMessage = string.Format ("onRtcStats callback duration {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}, tx(a) kbps: {5}, rx(a) kbps: {6} users {7}",
stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate, stats.txAudioKBitRate, stats.rxAudioKBitRate, stats.users);
Debug.Log (rtcStatsMessage);
int lengthOfMixingFile = mRtcEngine.GetAudioMixingDuration();
int currentTs = mRtcEngine.GetAudioMixingCurrentPosition();
string mixingMessage = string.Format ("Mixing File Meta {0}, {1}", lengthOfMixingFile, currentTs);
Debug.Log (mixingMessage);
};The OnRequestToken event listener for mRtcEngine triggers when the request token changes.
Set a debug log for the request key message requestKeyMessage using Debug.Log ().
mRtcEngine.OnRequestToken += () => {
string requestKeyMessage = string.Format ("OnRequestToken");
Debug.Log (requestKeyMessage);
};The OnConnectionInterrupted event listener for mRtcEngine triggers when the connection is interrupted.
Set a debug log for the interruption message interruptedMessage using Debug.Log ().
mRtcEngine.OnConnectionInterrupted += () => {
string interruptedMessage = string.Format ("OnConnectionInterrupted");
Debug.Log (interruptedMessage);
};The OnConnectionLost event listener for mRtcEngine triggers when the connection is lost.
Set a debug log for the connection lost message lostMessage using Debug.Log ().
mRtcEngine.OnConnectionLost += () => {
string lostMessage = string.Format ("OnConnectionLost");
Debug.Log (lostMessage);
};- Set the log filter for the engine using
mRtcEngine.SetLogFilter (). - Set the channel profile to
CHANNEL_PROFILE.GAME_FREE_MODEusingmRtcEngine.SetChannelProfile (). - Set the client role broadcaster by passing
CLIENT_ROLE.BROADCASTERintomRtcEngine.SetClientRole ().
mRtcEngine.SetLogFilter (LOG_FILTER.INFO);
mRtcEngine.SetChannelProfile (CHANNEL_PROFILE.GAME_FREE_MODE);The Update() method is invoked when the application updates.
If mRtcEngine is valid, invoke mRtcEngine.Poll ().
// Update is called once per frame
void Update ()
{
if (mRtcEngine != null) {
mRtcEngine.Poll ();
}
}The AgoraCanvas class has two methods to manage joining and leaving a channel.
The JoinChannel () method joins the user to the channel specified by the text input box mChannelNameInputField.
-
Set a debug log for
channelNameusingDebug.Log(), and ensurechannelNameis not null or empty, before executing the remaining code for the method. -
Join the channel using
mRtcEngine.JoinChannel ().
public void JoinChannel ()
{
string channelName = mChannelNameInputField.text.Trim ();
Debug.Log (string.Format ("tap joinChannel with channel name {0}", channelName));
if (string.IsNullOrEmpty (channelName)) {
return;
}
mRtcEngine.JoinChannel (channelName, "extra", 0);
}The LeaveChannel () method exits the user from the current channel.
Leave the channel using mRtcEngine.LeaveChannel().
public void LeaveChannel ()
{
mRtcEngine.LeaveChannel ();
}The MuteSelf() method mutes/unmutes the local audio stream using mRtcEngine.MuteLocalAudioStream().
public void MuteSelf (bool shouldMute) {
mRtcEngine.MuteLocalAudioStream (shouldMute);
}
The MuteButton class defines the mute button for the game scene.
The class defines 5 variables:
mutedImagefor the muted state icon.unmutedImagefor the unmuted state icon.agoraCanvasto communicate to/from theAgoraCanvasclass .myImageComponentto reference the button image.isMutedto indicate if the audio is muted / unmuted.
When the class starts, set gameObject to inactive using gameObject.SetActive().
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MuteButton : MonoBehaviour {
public Sprite mutedImage;
public Sprite unmutedImage;
public AgoraCanvas agoraCanvas;
Image myImageComponent;
private bool isMuted = false;
void Start () {
myImageComponent = GetComponent<Image> ();
gameObject.SetActive (false);
}
...
}
The SetHidden() method shows / hides the mute button and updates the game object.
If hidden is false, set isMuted to false and change the image for myImageComponent to unmutedImage.
Set the game object to active / inactive using gameObject.SetActive().
public void SetHidden (bool hidden) {
if (!hidden) {
isMuted = false;
myImageComponent.sprite = unmutedImage;
}
gameObject.SetActive (!hidden);
}
The mute button invokes the MuteClicked() method:
- Update
isMuted. - Update the image for
myImageComponentbased onisMuted. - Mute / unmute the user using
agoraCanvas.MuteSelf().
public void MuteClicked () {
isMuted = !isMuted;
myImageComponent.sprite = isMuted ? mutedImage : unmutedImage;
agoraCanvas.MuteSelf (isMuted);
}
The LoggerBridge class is a subclass of MonoBehaviour. The LoggerBridge.cs file contains the relevant logging code for the app.
The Start() and Update() methods are empty placeholder methods inherited from MonoBehaviour. Optional logs can be added if desired.
The doLog() method is a used for logging messages specified by msg using Debug.Log().
using System.Collections;
using UnityEngine;
public class LoggerBridge : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void doLog(string msg) {
Debug.Log (msg);
}
}Map the UI objects from the Unity UI to their respective classes.
In Unity, select the Canvas object created in the Add Agora UI to the Scene section.
-
Link
Canvasto theAgoraCanvasclass created in the Create the AgoraCanvas Class section. -
Link the following variables from the
AgoraCanvasclass:
| Script Panel Name | Class variable | Description |
|---|---|---|
| M Channel Name Input Field | mChannelNameInputField |
Link the channel text input component from the stage. |
| M Shown Message | mShownMessage |
Link the welcome text from the stage. |
| Version Text | versionText |
No link required. Version text can be optionally added. |
| Join Channel | joinChannel |
Link the Join Channel button from the stage. |
| Leave Channel | leaveChannel |
Link the Leave Channel button from the stage. |
| Mute Button | muteButton |
Link the mute button component from the stage. |
Select the MuteButton object created in the Add Agora UI to the Scene section.
-
Ensure the images for the mute button are set to Sprite objects by selecting Sprite (2D and UI) in the Texture Type dropdown menu.
-
Link the white muted image as the Target Graphic, to represent mute is inactive on first load.
-
Add the
MuteClickedmethod into the On Click() panel. -
Link
MuteButtonto theMuteButtonclass created in the Create the MuteButton Class section. -
Link the following variables from the
MuteButtonclass:
| Script Panel Name | Class variable | Description |
|---|---|---|
| Muted Image | mutedImage |
Link a blue muted image, to represent mute is active. |
| Unmuted Image | unmutedImage |
Link a white muted image, to represent mute is inactive. |
| Agora Canvas | agoraCanvas |
Link the Canvas object created in the Add Agora UI to the Scene section. |
Select the LoggerBridge object created in the Add Agora UI to the Scene section. Link LoggerBridge to the LoggerBridge class created in the Create the LoggerBridge Class section.
This section shows you how to prepare and build the app.
In order to build and run the sample application you must obtain an App ID:
- Create a developer account at agora.io. Once you finish the signup process, you will be redirected to the Dashboard.
- Navigate in the Dashboard tree on the left to Projects > Project List.
- Copy the App ID that you obtained from the Dashboard into a text file. You will use this when you launch the app.
-
Edit the
Assets/AgoraCanvas/AgoraCanvas.csfile. In theAgoraCanvasclass declaration, update#YOUR APP ID#with your App ID.private string appId = #YOUR APP ID#; -
Download the Agora Gaming SDK for Unity 3D.
-
Unzip the downloaded SDK package and copy the files from the following SDK folders into the associated sample application folders.
| SDK Folder | Application Folder |
|---|---|
libs/Android/ |
Assets/Plugins/Android/AgoraAudioKit.plugin/libs/ |
libs/iOS/ |
Assets/Plugins/iOS/ |
libs/Scripts/AgoraGamingSDK/ |
Assets/Scripts/AgoraGamingSDK/ |
- Open the project in Unity and run the sample application.
- A more complete demo of Agora Voice for Unity, can be found in the Spacewar with AMG Voice SDK for Unity project.
- Agora Video SDK samples are also available for the following platforms:
- Complete API documentation is available at the Document Center.
- You can file bugs about this sample here.
This software is under the MIT License (MIT). View the license.














