
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(
40 new string[] { Permission.Microphone, Permission.Camera },
41 callbacks
42 );
43 }
44 }
45 }
46
47 private void OnPermissionGranted(string permissionName)
48 {
49 // Debug.Log($"{permissionName} allowed by the user.");
50 }
51
52 // Called if permission denied
53 private void OnPermissionDenied(string permissionName) { }
54
55 // Called if permission denied with 'Don't Ask Again'
56 private void OnPermissionDeniedAndDontAskAgain(string permissionName) { }
57}
58Step 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
8 // Replace with your actual token from the VideoSDK dashboard
9 private readonly string _token = "YOUR_TOKEN";
10
11 void Start()
12 {
13 // Get the meeting object from the VideoSDK library
14 meeting = Meeting.GetMeetingObject();
15
16 // Show UI panels to create or join
17 _meetingJoinPanel.SetActive(true);
18 }
19
20 public void CreateMeeting()
21 {
22 Debug.Log("User requested to create a meeting ID...");
23
24 // Alert the user if microphone or camera permission is not granted.
25 AlertNoPermission();
26
27 _meetingJoinPanel.SetActive(false);
28
29 // This calls the SDK to generate a new Meeting ID
30 meeting.CreateMeetingId(_token);
31 }
32
33 public void JoinMeeting()
34 {
35 // If user typed a Meeting ID, we try to join
36 if (string.IsNullOrEmpty(_meetingIdInputField.text)) return;
37
38 // Alert the user if microphone or camera permission is not granted.
39 AlertNoPermission();
40
41 try
42 {
43 meeting.Join(
44 _token,
45 _meetingIdInputField.text,
46 "User",
47 true,
48 true
49 );
50 }
51 catch (System.Exception ex)
52 {
53 Debug.LogError("Join Meet Failed: " + ex.Message);
54 }
55 }
56
57 private void AlertNoPermission()
58 {
59 if (Application.platform == RuntimePlatform.Android)
60 {
61 if (!(Permission.HasUserAuthorizedPermission(Permission.Microphone) &&
62 Permission.HasUserAuthorizedPermission(Permission.Camera)))
63 {
64 Toast.Show(
65 $"You have not granted microphone or camera permission.",
66 3f,
67 Color.red,
68 ToastPosition.TopCenter
69 );
70 }
71 }
72 }
73}
74- 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.
Customizing Meeting and Participant IDs
The Join method allows developers to define custom values for meetingId and participantId:
1Join(
2 string token,
3 string meetingId,
4 string name,
5 bool micEnabled,
6 bool camEnabled,
7 string participantId = null
8)
9meetingIdcan 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
23 // Show create/join UI again
24 _meetingJoinPanel.SetActive(true);
25}
26OnCreateMeeting()→ 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
15 // ... (other callbacks)
16 _meetingJoinPanel.SetActive(true);
17}
18
19private void OnParticipantJoined(IParticipant participant)
20{
21 Debug.Log($"OnParticipantJoined: {participant.ToString()}");
22
23 // Instantiate a prefab that has a VideoSurface.
24 VideoSurface surface = Instantiate(
25 _videoSurfacePrefab,
26 _parent.transform
27 ).GetComponentInChildren<VideoSurface>();
28
29 surface.SetVideoSurfaceType(VideoSurfaceType.RawImage);
30 surface.SetParticipant(participant);
31 surface.SetEnable(true);
32
33 // Add to our tracking list
34 _participantList.Add(surface);
35
36 if (participant.IsLocal)
37 {
38 // Store the local participant separately
39 _localParticipant = surface;
40
41 // Show the meeting controls UI once we join
42 _meetingPanel.SetActive(true);
43 _meetingJoinPanel.SetActive(false);
44 _meetIdTxt.text = meeting.MeetingID;
45 }
46}
47
48private void OnParticipantLeft(IParticipant participant)
49{
50 Debug.Log($"OnParticipantLeft: {participant.ToString()}");
51
52 if (participant.IsLocal)
53 {
54 // If the local user leaves, do a cleanup
55 OnLeave();
56 }
57 else
58 {
59 // For remote participants, find the VideoSurface object and destroy it
60 VideoSurface surfaceToRemove = null;
61
62 for (int i = 0; i < _participantList.Count; i++)
63 {
64 if (obj.Id == _participantList[i].ParticipantId)
65 {
66 surfaceToRemove = _participantList[i];
67 _participantList.RemoveAt(i);
68 break;
69 }
70 }
71
72 if (surfaceToRemove != null)
73 {
74 Destroy(surfaceToRemove.transform.parent.gameObject);
75 }
76 }
77}
78
79private void OnLeave()
80{
81 // We'll implement this method in the next step.
82}
83- 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 = false;
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 = false;
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
39 _participantList.Clear();
40
41 // Reset text
42 _meetingIdTxt.text = "VideoSDK Unity Demo";
43}
44Step 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.
1private void OnParticipantJoined(IParticipant participant)
2{
3 //...
4
5 if (participant.IsLocal)
6 {
7 //...
8
9 // Store the local participant separately
10 _localParticipant = surface;
11
12 // Subscribed callback function to delegate
13 _localParticipant.OnStreamEnableCallback += OnStreamEnable;
14 _localParticipant.OnStreamDisableCallback += OnStreamDisable;
15
16 //...
17 }
18}
19
20private void OnStreamEnable(StreamKind kind)
21{
22 // Called when camera or mic is enabled
23 camToggle = _localParticipant.CamEnabled;
24 micToggle = _localParticipant.MicEnabled;
25}
26
27private void OnStreamDisable(StreamKind kind)
28{
29 // Called when camera or mic is disabled
30 camToggle = _localParticipant.CamEnabled;
31 micToggle = _localParticipant.MicEnabled;
32}
33Done! 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!
