
Prerequisites
Before getting started, make sure you have the following:
- Unity Setup: Unity Hub and Unity Editor (version 2018.4.0 or later)
- Development Environment:
- Android: Android 4.1+ with Android Studio 4.1+
- iOS: iOS 10.15+ with Xcode 9.0+
- Accounts:
- A VideoSDK account to generate a token.
Install VideoSDK package
Open Unity’s Package Manager by selecting from the top bar: Window -> Package Manager.
Click the + button in the top left corner and select Add package from git URL...
Paste the following URL and click Add:
1https://github.com/videosdk-live/videosdk-rtc-unity-sdk.git
2
- Add the
com.unity.nuget.newtonsoft-jsonpackage by following the instructions provided here.
Setup Instructions
Android Setup
To integrate the VideoSDK into your Android project, follow these steps:
- Add the following repository configuration to your
settingsTemplate.gradlefile:
1dependencyResolutionManagement {
2 repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
3 repositories {
4 **ARTIFACTORYREPOSITORY**
5 google()
6 mavenCentral()
7 jcenter()
8 maven {
9 url = uri("https://maven.aliyun.com/repository/jcenter")
10 }
11 flatDir {
12 dirs "${project(':unityLibrary').projectDir}/libs"
13 }
14 }
15}
16- Install Android SDK in
mainTemplate.gradle
1dependencies {
2 implementation 'live.videosdk:rtc-android-sdk:0.3.1'
3}
4- If your project has set
android.useAndroidX=true, then setandroid.enableJetifier=truein thegradleTemplate.propertiesfile to migrate your project to AndroidX and avoid duplicate class conflict.
1android.enableJetifier = true;
2android.useAndroidX = true;
3android.suppressUnsupportedCompileSdk = 34;
4Setting Up for iOS
- Build for iOS: In Unity, export the project for iOS.
- Open in Xcode: Navigate to the generated Xcode project and open it.
- Configure Frameworks:
- Select the Unity-iPhone target.
- Go to the General tab.
- Under Frameworks, Libraries, and Embedded Content, add VideoSDK and its required frameworks.

Steps for Setting Up a Conference in Unity
VideoSDK helps you add audio/video calling capabilities to your Unity app in minutes. This quick start shows you how to request camera/mic permissions, create or join a meeting, and display participant video feeds inside Unity’s RawImage components, all while handling toggles for microphone, camera, and leaving the meeting.

Step 1: Create a Basic UI
When you start a new Unity project, a default scene named "Sample" is created for you. We will use this scene to set up the user interface for our audio/video calling feature. In this step, we will create a user interface in Unity for a video meeting system. The UI will have two main panels:
Joining Panel – where users can either create or join a meeting.
Meeting Panel – where participants interact during a meeting.
Creating the Joining Panel
The Joining Panel allows users to create or join a meeting by entering a unique meeting code.
In your Unity project, right-click the Sample Scene and select GameObject > UI > Panel.
Rename the panel to MettingJoinPanel in the Inspector window.
Right-click MettingJoinPanel and select UI > Button - TextMeshPro. Rename this button to CreateMeeting.
- Set position: X: 0px, Y: 150px.
- Set size: Width: 250px, Height: 100px.
Repeat the previous step to create another button named JoinMeeting.
- Set position: X: 0px, Y: -150px.
- Set size: Width: 250px, Height: 100px.
Create an InputField:
- Right-click MettingJoinPanel and select UI > InputField - TextMeshPro. Rename it MeetingIdInput.
- Set position: X: 0px, Y: 0px.
- Set size: Width: 450px, Height: 120px.
Creating the Meeting Panel
The Meeting Panel is where participants interact during an ongoing meeting. It includes video frames for participants and control buttons for managing the meeting.
Right-click Canvas and select UI > Panel. Rename it MeetingPanel.
Create a controls section:
- Right-click MeetingPanel, select Create Empty, and rename it Controls.
- Set Controls to stretch to the bottom of the panel.
- Set position: Y: 38px.
- Set size: Height: 100px.
Add control buttons:
- Right-click Controls and select UI > Button - TextMeshPro.
- Rename it Mic and set:
- Position: X: -315px, Y: 0px.
- Size: Width: 200px, Height: 100px.
- Duplicate Mic and rename the new buttons LeaveMeeting and WebCam.
- Set LeaveMeeting position: X: 0px, Y: 0px.
- Set WebCam position: X: 315px, Y: 0px.
- Keep size: Width: 200px, Height: 100px.
Create a video frames container:
- Right-click MeetingPanel, select Create Empty, and rename it Participants.
- Set Participants to stretch to the top of the panel.
- Set position: Y: -185px.
- Set size: Height: 900px.
- Add a Grid Layout Group component:
- Set Cell Size: X: 350px, Y: 400px.
- Set Spacing: X: 20px, Y: 20px.
Add a Meeting ID text label:
- Right-click MeetingPanel and select UI > Text - TextMeshPro.
- Rename it MeetingId.
- Set it to stretch to the top of the panel.
- Set size: Height: 150px.
- This will display the current meeting's unique ID.
Creating Video View Prefabs
Each participant's video feed will be represented by a Participant prefab.
Create an empty GameObject and rename it Participant.
- Set size: Width: 350px, Height: 450px.
Add a Raw Image:
- Right-click Participant and select UI > Raw Image.
- Set it to stretch fully.
Attach the VideoSurface.cs script:
- Navigate to Packages > VideoSDK > Runtime.
- Drag and drop VideoSurface.cs onto the Raw Image.
Step 2: Managing UI Elements & Permissions
To enable camera and microphone access on Android, you must declare the required permissions in your AndroidManifest.xml. Add the following lines inside the <manifest> tag and before the <application> tag:
1<manifest>
2
3 <uses-permission android:name="android.permission.CAMERA"/>
4 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
5 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
6
7 <application>
8 <...>
9 </application>
10</manifest>
11Next, Configure the UI fields and request camera/mic access. In your GameManager.cs, define the serialized fields for UI references and the method that checks permissions on Android. The code snippet below covers:
- Declaring
_meetingJoinPanel,_meetingPanelto show/hide panels. - Requesting
Permission.CameraandPermission.Microphone.
1using System.Collections.Generic;
2using UnityEngine;
3using live.videosdk;
4using UnityEngine.Android;
5using TMPro; // For TextMeshPro references
6using EasyUI.Toast; // For quick notifications (optional)
7
8public class GameManager : MonoBehaviour
9{
10 [SerializeField] GameObject _meetingJoinPanel;
11 [SerializeField] GameObject _meetingPanel;
12
13 private void Awake()
14 {
15 // Hide UI sections initially
16 _meetingJoinPanel.SetActive(false);
17 _meetingPanel.SetActive(false);
18
19 // Request for Camera and Mic Permission
20 RequestForPermission();
21 }
22
23 private void RequestForPermission()
24 {
25 if (Application.platform == RuntimePlatform.Android)
26 {
27 if (Permission.HasUserAuthorizedPermission(Permission.Microphone) &&
28 Permission.HasUserAuthorizedPermission(Permission.Camera))
29 {
30 // The user authorized use of the microphone and camera.
31 OnPermissionGranted(string.Empty);
32 }
33 else
34 {
35 var callbacks = new PermissionCallbacks();
36 callbacks.PermissionDenied += OnPermissionDenied;
37 callbacks.PermissionGranted += OnPermissionGranted;
38 callbacks.PermissionDeniedAndDontAskAgain += OnPermissionDeniedAndDontAskAgain;
39 Permission.RequestUserPermissions(new string[] { Permission.Microphone, Permission.Camera }, callbacks);
40 }
41 }
42 }
43
44 private void OnPermissionGranted(string permissionName)
45 {
46 // Debug.Log($"{permissionName} allowed by the user.");
47 }
48
49 // Called if permission denied
50 private void OnPermissionDenied(string permissionName) { }
51 // Called if permission denied with 'Don't Ask Again'
52 private void OnPermissionDeniedAndDontAskAgain(string permissionName) { }
53}
54Step 3: Creating or Joining a Meeting
Next, let's hook up the VideoSDK meeting object. We’ll add these code blocks to Start() and define two simple methods: CreateMeeting() and JoinMeeting(). This sets up meeting creation (to get a new Meeting ID) or direct joining (when the user has an existing ID).
1public class GameManager : MonoBehaviour
2{
3 [SerializeField] TMP_Text _meetingIdTxt;
4 [SerializeField] TMP_InputField _meetingIdInputField;
5
6 private Meeting meeting;
7 // Replace with your actual token from the VideoSDK dashboard
8 private readonly string _token = "YOUR_TOKEN";
9
10 void Start()
11 {
12 // Get the meeting object from the VideoSDK library
13 meeting= Meeting.GetMeetingObject();
14 // Show UI panels to create or join
15 _meetingJoinPanel.SetActive(true);
16 }
17
18 public void CreateMeeting()
19 {
20 Debug.Log("User requested to create a meeting ID...");
21 // Alert the user if microphone or camera permission is not granted.
22 AlertNoPermission();
23 _meetingJoinPanel.SetActive(false);
24 // This calls the SDK to generate a new Meeting ID
25 meeting.CreateMeetingId(_token);
26 }
27
28 public void JoinMeeting()
29 {
30 // If user typed a Meeting ID, we try to join
31 if (string.IsNullOrEmpty(_meetingIdInputField.text)) return;
32 // Alert the user if microphone or camera permission is not granted.
33 AlertNoPermission();
34 try
35 {
36 meeting.Join(_token, _meetingIdInputField.text, "User", true, true);
37 }
38 catch (System.Exception ex)
39 {
40 Debug.LogError("Join Meet Failed: " + ex.Message);
41 }
42 }
43
44 private void AlertNoPermission()
45 {
46 if (Application.platform == RuntimePlatform.Android)
47 {
48 if (!(Permission.HasUserAuthorizedPermission(Permission.Microphone) && Permission.HasUserAuthorizedPermission(Permission.Camera)))
49 {
50 Toast.Show($"You have not granted microphone or camera permission.", 3f, Color.red, ToastPosition.TopCenter);
51 }
52 }
53 }
54}
55- Assign
CreateMeeting()to the CreateMeeting button through inspector. - Assign
JoinMeeting()to the JoinMeeting button through inspector. - The
AlertNoPermission()method is alert the user if microphone or camera permission is not granted. - The
CreateMeeting()method callsmeeting.CreateMeetingId(_token). - Once that’s successful,
OnCreateMeetingIdCallbackcallback will provide the new Meeting ID. JoinMeeting()directly callsmeeting.Join(...)if the user typed in an existing ID.
Tip: Customizing Meeting and Participant IDs
The
Joinmethod allows developers to define custom values formeetingIdandparticipantId:
Join(string token, string meetingId, string name, bool micEnabled, bool camEnabled, string participantId = null)
meetingIdcan be structured in any preferred format by the developer, e.g.,aaaa-bbbborxxxx-yyyy, instead of following a predefined pattern.participantIdcan also be set by the developer, but it must be unique for each participant in a meeting.
Callbacks for Create Meeting
To know when a new meeting has been created, we register callback methods in Start().
1void Start()
2{
3 meeting = Meeting.GetMeetingObject();
4
5 // --- Register Callbacks ---
6 meeting.OnCreateMeetingIdCallback += OnCreateMeeting;
7 meeting.OnCreateMeetingIdFailedCallback += OnCreateMeetingFailed;
8
9 //...
10}
11
12private void OnCreateMeeting(string meetingId)
13{
14 // Once a new meeting ID is generated, join automatically
15 _meetingIdTxt.text = meetingId; // Display on screen
16 meeting.Join(_token, meetingId, "User", true, true);
17}
18
19private void OnCreateMeetingFailed(string errorMsg)
20{
21 Debug.LogError(errorMsg);
22 // Show create/join UI again
23 _meetingJoinPanel.SetActive(true);
24}
25OnCreateMeeting()→ success callback forCreateMeetingId(...).OnCreateMeetingFailed()→ reverts to the UI on failure.
Step 4: Managing Participants & Video Rendering
Now for the fun part: showing participant streams. The OnParticipantJoined callback will fire each time someone (including your local user) joins the meeting. Above we created a prefab with a VideoSurface component to map their stream onto a RawImage.
1[SerializeField] GameObject _videoSurfacePrefab;
2[SerializeField] Transform _parent;
3
4private List<VideoSurface> _participantList = new List<VideoSurface>();
5private VideoSurface _localParticipant;
6
7void Start()
8{
9 meeting= Meeting.GetMeetingObject();
10
11 meeting.OnCreateMeetingIdCallback += OnCreateMeeting;
12 meeting.OnParticipantJoinedCallback += OnParticipantJoined;
13 meeting.OnParticipantLeftCallback += OnParticipantLeft;
14 // ... (other callbacks)
15 _meetingJoinPanel.SetActive(true);
16}
17
18private void OnParticipantJoined(IParticipant participant)
19{
20 Debug.Log($"OnParticipantJoined: {participant.ToString()}");
21
22 // Instantiate a prefab that has a VideoSurface.
23 VideoSurface surface = Instantiate(_videoSurfacePrefab, _parent.transform).GetComponentInChildren<VideoSurface>();
24
25 surface.SetVideoSurfaceType(VideoSurfaceType.RawImage);
26 surface.SetParticipant(participant);
27 surface.SetEnable(true);
28
29 // Add to our tracking list
30 _participantList.Add(surface);
31
32 if (participant.IsLocal)
33 {
34 // Store the local participant separately
35 _localParticipant = surface;
36
37 // Show the meeting controls UI once we join
38 _meetingPanel.SetActive(true);
39 _meetingJoinPanel.SetActive(false);
40 _meetIdTxt.text = meeting.MeetingID;
41 }
42}
43
44private void OnParticipantLeft(IParticipant participant)
45{
46 Debug.Log($"OnParticipantLeft: {participant.ToString()}");
47
48 if (participant.IsLocal)
49 {
50 // If the local user leaves, do a cleanup
51 OnLeave();
52 }
53 else
54 {
55 // For remote participants, find the VideoSurface object and destroy it
56 VideoSurface surfaceToRemove = null;
57 for (int i = 0; i < _participantList.Count; i++)
58 {
59 if(obj.Id == _participantList[i].ParticipantId)
60 {
61 surfaceToRemove = _participantList[i];
62 _participantList.RemoveAt(i);
63 break;
64 }
65 }
66 if (surfaceToRemove != null)
67 {
68 Destroy(surfaceToRemove.transform.parent.gameObject);
69 }
70 }
71}
72
73private void OnLeave(){
74 // We'll implement this method in the next step.
75}
76- Create a prefab with a
RawImagechild that has aVideoSurfacecomponent - Drag that prefab into
_videoSurfacePrefabin the Inspector _parentis a Transform where participant video windows appear.
Step 5: Creating Controls - Toggling Camera, Mic & Leaving
To provide users with essential meeting controls, the following functions handle toggling the camera, microphone, and exiting the session:
Toggle Camera →
CamToggle()enables or disables the participant's video feed.Toggle Mic →
AudioToggle()allows participants to mute or unmute their microphone.Leave Meeting →
LeaveMeeting()gracefully exits the session by callingmeeting.Leave(), ensuring proper cleanup.Assign
AudioToggle()to the Mic button through inspector.Assign
CamToggle()to the WebCam button through inspector.Assign
LeaveMeeting()to the LeaveMeeting button through inspector.
1private bool camToggle = true;
2private bool micToggle = true;
3
4public void CamToggle()
5{
6 camToggle = !camToggle;
7 Debug.Log("Cam Toggle: " + camToggle);
8 _localParticipant?.SetVideo(camToggle);
9}
10
11public void AudioToggle()
12{
13 micToggle = !micToggle;
14 Debug.Log("Mic Toggle: " + micToggle);
15 _localParticipant?.SetAudio(micToggle);
16}
17
18public void LeaveMeeting()
19{
20 meeting?.Leave();
21}
22
23private void OnLeave()
24{
25 // Clean up local UI
26 _meetingJoinPanel.SetActive(true);
27 _meetingPanel.SetActive(false);
28
29 // Reset toggles
30 camToggle = true;
31 micToggle = true;
32
33 // Destroy all participant surfaces
34 for (int i = 0; i < _participantList.Count; i++)
35 {
36 Destroy(_participantList[i].transform.parent.gameObject);
37 }
38 _participantList.Clear();
39
40 // Reset text
41 _meetingIdTxt.text = "VideoSDK Unity Demo";
42}
43Step 6: Listening to Callbacks releated to stream
- When a participant joins, if they are the local participant,
OnStreamEnableandOnStreamDisableare added to the callbacksOnStreamEnableCallbackandOnStreamDisableCallback.
These functions handle the enabling and disabling of the local participant's camera and microphone:
OnStreamEnable: Triggered when the camera or microphone is enabled, updating the toggle states.OnStreamDisable: Triggered when the camera or microphone is disabled, updating the toggle states.
1 private void OnParticipantJoined(IParticipant participant)
2 {
3 //...
4 if (participant.IsLocal)
5 {
6 //...
7
8 // Store the local participant separately
9 _localParticipant = surface;
10
11 //Subscribed callback function to delegate
12 _localParticipant.OnStreamEnableCallback += OnStreamEnable;
13 _localParticipant.OnStreamDisableCallback += OnStreamDisable;
14
15 //...
16 }
17 }
18 private void OnStreamEnable(StreamKind kind)
19 {
20 // Called when camera or mic is enabled
21 camToggle = _localParticipant.CamEnabled;
22 micToggle = _localParticipant.MicEnabled;
23 }
24 private void OnStreamDisable(StreamKind kind)
25 {
26 // Called when camera or mic is disabled
27 camToggle = _localParticipant.CamEnabled;
28 micToggle = _localParticipant.MicEnabled;
29 }
30Done! Full Example Code
Following the steps above, you’ll end up with a GameManager.cs that handles requesting permissions, creating/joining a meeting, showing participant video streams, and managing toggles. To see the complete code in one place, visit: GameManager.cs on GitHub
You can copy it into your project, ensure your UI references are wired up in the Inspector, and you’re set!
