Skip to content

Commit

Permalink
Add Livekit Videochat Integration
Browse files Browse the repository at this point in the history
- Added `LivekitVideo.cs` and `LivekitVideoManager.cs` to `Assets/SEE/Tools/Videochat/`
  - `LivekitVideo.cs`: Handles the positioning of video streams. It renames the GameObject so that `LivekitVideoManager` can access it later.
  - `LivekitVideoManager.cs`: Manages communication with the media server and handles incoming video streams.

- Updated `BaseAvatar` prefab in `Assets/Resources/Prefabs/Players/CC4/`
  - Added a new child object with the following components:
    - `Mesh Filter` (set to `Quad`)
    - `Mesh Renderer` (using `ExampleMaterial` with the shader set to `Unlit/Texture`, `Receive Shadows`=disabled)
    - `LivekitVideo.cs`
  - The scale of the new child object is set to `x=0.2, y=0.2, z=-1`.
  - The `Mesh Renderer` is initially disabled and will be activated by the `LivekitVideoManager.cs` script.

- Removed the old `FaceCam` object from the `BaseAvatar` prefab.

- Modified the `SEENewWorld` scene:
  - Added a new `Canvas` object with the `LivekitVideoManager.cs` script attached.
  - Configured the `Livekit Url` to point to the media server (SFU) responsible for distributing video streams.
  - Configured the `Token Url` for the token server providing access to the media server.
  - Set the `Room Name`, ensuring that no two sessions use the same room name simultaneously to avoid conflicts.

- Added a `TextMeshPro Dropdown` to the Canvas for listing available cameras, which is linked to `LivekitVideoManager`.

- Updated `Assets/SEE/SEE.asmdef` to include `Packages/io.livekit.livekit-sdk/Runtime/livekit.unity.Runtime.asmdef`
  • Loading branch information
pit2710 committed Sep 27, 2024
1 parent 1202cff commit 12a4594
Show file tree
Hide file tree
Showing 10 changed files with 2,716 additions and 704 deletions.
174 changes: 98 additions & 76 deletions Assets/Resources/Prefabs/Players/CC4/BaseAvatar.prefab
Original file line number Diff line number Diff line change
@@ -1,5 +1,101 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7371686504643218549
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7818067836775645936}
- component: {fileID: 6700312742812911419}
- component: {fileID: 125735865005071757}
- component: {fileID: 108957911249939627}
m_Layer: 0
m_Name: LivekitVideo
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7818067836775645936
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7371686504643218549}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0.34305736, y: 1.7508266, z: -0.046694104}
m_LocalScale: {x: 0.2, y: 0.2, z: -1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1242937920193830085}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6700312742812911419
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7371686504643218549}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &125735865005071757
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7371686504643218549}
m_Enabled: 0
m_CastShadows: 1
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 82cedaac19e0a3e40a59d980c2efc68e, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &108957911249939627
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7371686504643218549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 814d03533fbb9a8409b921253838f2de, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &7978100806410315116
GameObject:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -398,11 +494,11 @@ PrefabInstance:
- targetCorrespondingSourceObject: {fileID: -8679921383154817045, guid: b93f96cf429b12342ac1893df03cdecb,
type: 3}
insertIndex: -1
addedObject: {fileID: 3145899081293580556}
addedObject: {fileID: 1191248758004378816}
- targetCorrespondingSourceObject: {fileID: -8679921383154817045, guid: b93f96cf429b12342ac1893df03cdecb,
type: 3}
insertIndex: -1
addedObject: {fileID: 1191248758004378816}
addedObject: {fileID: 7818067836775645936}
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: b93f96cf429b12342ac1893df03cdecb,
type: 3}
Expand Down Expand Up @@ -6867,77 +6963,3 @@ Animator:
type: 3}
m_PrefabInstance: {fileID: 1636341645340932910}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &5520162690213855426
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 1242937920193830085}
m_Modifications:
- target: {fileID: 7436555913008548298, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_Name
value: FaceCam
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalPosition.y
value: 1.959
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 79fdfce9bfebc62439ecae0fddc018e4, type: 3}
--- !u!4 &3145899081293580556 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7436555913008548302, guid: 79fdfce9bfebc62439ecae0fddc018e4,
type: 3}
m_PrefabInstance: {fileID: 5520162690213855426}
m_PrefabAsset: {fileID: 0}
3 changes: 2 additions & 1 deletion Assets/SEE/SEE.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"GUID:fe685ec1767f73d42b749ea8045bfe43",
"GUID:5c01796d064528144a599661eaab93a6",
"GUID:e0cd26848372d4e5c891c569017e11f1",
"GUID:13e34609dade4964e97712dc04b1cc6a"
"GUID:13e34609dade4964e97712dc04b1cc6a",
"GUID:702f733b4deb246808c6ce84d93b5c9c"
],
"includePlatforms": [],
"excludePlatforms": [],
Expand Down
8 changes: 8 additions & 0 deletions Assets/SEE/Tools/Videochat.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d273552ff1475b4dbd45307424a9609
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
97 changes: 97 additions & 0 deletions Assets/SEE/Tools/Videochat/LivekitVideo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using UnityEngine;
using Unity.Netcode;
using SEE.Controls;
using SEE.Utils;

public class LivekitVideo : NetworkBehaviour
{
/// <summary>
/// The object with the position where the player's head is located.
/// </summary>
private Transform playerHead;

/// <summary>
/// The relative path to the bone of the player's head.
/// This is used to position the Livekit video.
/// </summary>
private const string faceCamOrientationBone = "CC_Base_BoneRoot/CC_Base_Hip/CC_Base_Waist/CC_Base_Spine01/CC_Base_Spine02/CC_Base_NeckTwist01/CC_Base_NeckTwist02/CC_Base_Head";

/// <summary>
/// The status of the position of the Livekit video.
/// Can be positioned in front of the face or above the face, tilted towards the observer.
/// When <c>faceCamOnFront</c> is true, the video is positioned in front of the face using <c>offsetInFrontOfFace</c>.
/// When <c>faceCamOnFront</c> is false, the video is positioned above the head using <c>offsetAboveHead</c>.
/// </summary>
private bool faceCamOnFront = true;

/// <summary>
/// Offset for positioning the video in front of the player's face.
/// Used when <c>faceCamOnFront</c> is true.
/// </summary>
private Vector3 offsetInFrontOfFace = new Vector3(0, 0.065f, 0.15f);

/// <summary>
/// Offset for positioning the video above the player's head.
/// Used when <c>faceCamOnFront</c> is false.
/// </summary>
private Vector3 offsetAboveHead = new Vector3(0, 0.35f, 0);

/// <summary>
/// Called when the script instance is being loaded.
/// Initializes the player head reference and sets the object name so that it contains the owner ID of the client.
/// </summary>
private void Start()
{
// Set the name of the object to "LivekitVideo_" followed by the owner client ID.
gameObject.name = "LivekitVideo_" + OwnerClientId;

// Localizes the player's head bone for the positioning of the video.
playerHead = transform.parent.Find(faceCamOrientationBone);
}

/// <summary>
/// Called once per frame to update the position and rotation of the video.
/// Toggles the position of the video between above the player's head or in front of it.
/// The position can be toggled with <see cref="SEEInput.ToggleFaceCamPosition"/>.
/// </summary>
private void Update()
{
// Update the video position when the player's head is found.
if (playerHead != null)
{
UpdatePosition();
}

// Check for input to toggle the video position.
if (SEEInput.ToggleFaceCamPosition())
{
faceCamOnFront = !faceCamOnFront;
}
}

/// <summary>
/// Updates the position and orientation of the video based on the player's head.
/// </summary>
/// <remarks>If the video is positioned in front of the player's face, it follows
/// the head's position and rotation. If positioned above the head, it faces the camera
/// for remote clients.</remarks>
private void UpdatePosition()
{
if (faceCamOnFront)
{
// Position the video in front of the player's face.
transform.SetPositionAndRotation(playerHead.TransformPoint(offsetInFrontOfFace), playerHead.rotation);
}
else
{
// Position the video above the player's head.
transform.position = playerHead.TransformPoint(offsetAboveHead);

// If this object is not owned by the local client, make it face the main camera.
if (!IsOwner && MainCamera.Camera != null)
{
transform.LookAt(MainCamera.Camera.transform);
}
}
}
}
11 changes: 11 additions & 0 deletions Assets/SEE/Tools/Videochat/LivekitVideo.cs.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 814d03533fbb9a8409b921253838f2de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
Loading

0 comments on commit 12a4594

Please sign in to comment.