【m】优化socket代码

This commit is contained in:
2026-04-29 15:13:24 +08:00
parent 753878bdbb
commit 231021d318
127 changed files with 807 additions and 44137 deletions

View File

@@ -29,6 +29,14 @@ namespace Unity.RenderStreaming
s_AddChannelHandler = Execute;
private static readonly ExecuteEvents.EventFunction<IAddReceiverHandler>
s_AddReceiverHandler = Execute;
private static readonly ExecuteEvents.EventFunction<IParticipantJoinedHandler>
s_ParticipantJoinedHandler = Execute;
private static readonly ExecuteEvents.EventFunction<IParticipantLeftHandler>
s_ParticipantLeftHandler = Execute;
private static readonly ExecuteEvents.EventFunction<ICallRequestHandler>
s_CallRequestHandler = Execute;
private static readonly ExecuteEvents.EventFunction<IMessageHandler>
s_MessageHandler = Execute;
private static void Execute(ICreatedConnectionHandler handler, BaseEventData eventData)
{
@@ -62,6 +70,22 @@ namespace Unity.RenderStreaming
{
handler.OnAddReceiver(ValidateEventData<SignalingEventData>(eventData));
}
private static void Execute(IParticipantJoinedHandler handler, BaseEventData eventData)
{
handler.OnParticipantJoined(ValidateEventData<SignalingEventData>(eventData));
}
private static void Execute(IParticipantLeftHandler handler, BaseEventData eventData)
{
handler.OnParticipantLeft(ValidateEventData<SignalingEventData>(eventData));
}
private static void Execute(ICallRequestHandler handler, BaseEventData eventData)
{
handler.OnCallRequest(ValidateEventData<SignalingEventData>(eventData));
}
private static void Execute(IMessageHandler handler, BaseEventData eventData)
{
handler.OnMessage(ValidateEventData<SignalingEventData>(eventData));
}
public static ExecuteEvents.EventFunction<ICreatedConnectionHandler> createdConnectionHandler
{
@@ -96,6 +120,22 @@ namespace Unity.RenderStreaming
{
get { return s_AddReceiverHandler; }
}
public static ExecuteEvents.EventFunction<IParticipantJoinedHandler> participantJoinedHandler
{
get { return s_ParticipantJoinedHandler; }
}
public static ExecuteEvents.EventFunction<IParticipantLeftHandler> participantLeftHandler
{
get { return s_ParticipantLeftHandler; }
}
public static ExecuteEvents.EventFunction<ICallRequestHandler> callRequestHandler
{
get { return s_CallRequestHandler; }
}
public static ExecuteEvents.EventFunction<IMessageHandler> messageHandler
{
get { return s_MessageHandler; }
}
}

View File

@@ -0,0 +1,243 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.RenderStreaming
{
/// <summary>
/// Host模式的连接处理器
/// 适用于私有模式下Unity作为Host第一个加入房间的客户端
/// 支持多个Participant连接每个Participant拥有独立的PeerConnection
///
/// 工作原理:
/// - Host通过CreateConnection(connectionId)创建房间连接
/// - 当Participant加入时服务器发送participant-joined通知
/// - WebSocketSignaling将participantId作为内部connectionId使用
/// 因此每个Participant会自动创建独立的PeerConnection
/// - 当收到Participant的offer时自动添加Stream并发送answer
/// - 当Participant离开时自动清理对应的连接资源
/// </summary>
[AddComponentMenu("Render Streaming/Host Connection")]
public class HostConnection : SignalingHandlerBase,
IOfferHandler, IAddChannelHandler, IDisconnectHandler, IDeletedConnectionHandler,
IAddReceiverHandler, IParticipantJoinedHandler, IParticipantLeftHandler,
ICallRequestHandler, IMessageHandler
{
[SerializeField] private List<Component> streams = new List<Component>();
/// <summary>
/// 当前连接的所有Participant的participantId列表
/// </summary>
private List<string> participantIds = new List<string>();
/// <summary>
/// 房间的connectionIdHost创建连接时使用的ID
/// </summary>
private string roomConnectionId;
public override IEnumerable<Component> Streams => streams;
public void AddComponent(Component component)
{
streams.Add(component);
}
public void RemoveComponent(Component component)
{
streams.Remove(component);
}
/// <summary>
/// 创建Host连接即创建房间
/// Unity作为第一个连接的客户端服务器会分配host角色(polite=false)
/// </summary>
/// <param name="connectionId">房间ID</param>
public override void CreateConnection(string connectionId)
{
roomConnectionId = connectionId;
base.CreateConnection(connectionId);
}
/// <summary>
/// 删除Host连接关闭房间
/// Host离开时服务器会自动断开所有Participant
/// </summary>
public override void DeleteConnection(string connectionId)
{
// 清理所有Participant连接
foreach (var participantId in participantIds.ToList())
{
DisconnectParticipant(participantId);
}
participantIds.Clear();
if (connectionId == roomConnectionId)
{
base.DeleteConnection(connectionId);
roomConnectionId = null;
}
else
{
base.DeleteConnection(connectionId);
}
}
public void OnDeletedConnection(SignalingEventData eventData)
{
Disconnect(eventData.connectionId);
}
public void OnDisconnect(SignalingEventData eventData)
{
Disconnect(eventData.connectionId);
}
private void Disconnect(string connectionId)
{
if (!participantIds.Contains(connectionId) && connectionId != roomConnectionId)
return;
participantIds.Remove(connectionId);
foreach (var sender in streams.OfType<IStreamSender>())
{
RemoveSender(connectionId, sender);
}
foreach (var receiver in streams.OfType<IStreamReceiver>())
{
RemoveReceiver(connectionId, receiver);
}
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == connectionId))
{
RemoveChannel(connectionId, channel);
}
}
/// <summary>
/// 断开指定Participant的连接资源
/// </summary>
private void DisconnectParticipant(string participantId)
{
foreach (var sender in streams.OfType<IStreamSender>())
{
RemoveSender(participantId, sender);
}
foreach (var receiver in streams.OfType<IStreamReceiver>())
{
RemoveReceiver(participantId, receiver);
}
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == participantId))
{
RemoveChannel(participantId, channel);
}
}
/// <summary>
/// 收到Participant的offer时触发
/// WebSocketSignaling已经将participantId作为内部connectionId
/// 所以每个Participant的offer会自动创建独立的PeerConnection
/// </summary>
public void OnOffer(SignalingEventData data)
{
// 记录新的Participant连接
if (!participantIds.Contains(data.connectionId))
{
participantIds.Add(data.connectionId);
Debug.Log($"[HostConnection] Participant offer received: {data.connectionId}");
}
// 为该Participant添加所有Stream
foreach (var source in streams.OfType<IStreamSender>())
{
AddSender(data.connectionId, source);
}
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.IsLocal))
{
AddChannel(data.connectionId, channel);
}
// 发送answer给该Participant
SendAnswer(data.connectionId);
}
/// <summary>
/// 收到远程Track时触发
/// </summary>
public void OnAddReceiver(SignalingEventData data)
{
var track = data.transceiver.Receiver.Track;
IStreamReceiver receiver = GetReceiver(track.Kind);
SetReceiver(data.connectionId, receiver, data.transceiver);
}
/// <summary>
/// 收到远程DataChannel时触发
/// </summary>
public void OnAddChannel(SignalingEventData data)
{
var channel = streams.OfType<IDataChannel>().
FirstOrDefault(r => !r.IsConnected && !r.IsLocal);
channel?.SetChannel(data.connectionId, data.channel);
}
/// <summary>
/// 新Participant加入房间通知
/// 在私有模式下服务器会通知Host有新的Participant加入
/// 此时不做额外处理等收到Participant的offer时再建立连接
/// </summary>
public void OnParticipantJoined(SignalingEventData eventData)
{
Debug.Log($"[HostConnection] Participant joined: connectionId={eventData.connectionId}, participantId={eventData.participantId}");
}
/// <summary>
/// Participant离开房间通知
/// 清理该Participant的连接资源
/// </summary>
public void OnParticipantLeft(SignalingEventData eventData)
{
string participantId = eventData.participantId;
if (!string.IsNullOrEmpty(participantId))
{
Debug.Log($"[HostConnection] Participant left: connectionId={eventData.connectionId}, participantId={participantId}");
DisconnectParticipant(participantId);
participantIds.Remove(participantId);
}
}
/// <summary>
/// 收到呼叫请求
/// </summary>
public void OnCallRequest(SignalingEventData eventData)
{
Debug.Log($"[HostConnection] Call request from: {eventData.connectionId}, data: {eventData.message}");
}
/// <summary>
/// 收到自定义消息
/// </summary>
public void OnMessage(SignalingEventData eventData)
{
Debug.Log($"[HostConnection] Message from: {eventData.connectionId}, participantId: {eventData.participantId}, message: {eventData.message}");
}
/// <summary>
/// 获取当前连接的Participant数量
/// </summary>
public int ParticipantCount => participantIds.Count;
/// <summary>
/// 获取所有Participant的ID列表
/// </summary>
public IReadOnlyList<string> ParticipantIds => participantIds.AsReadOnly();
IStreamReceiver GetReceiver(WebRTC.TrackKind kind)
{
if (kind == WebRTC.TrackKind.Audio)
return streams.OfType<AudioStreamReceiver>().FirstOrDefault();
if (kind == WebRTC.TrackKind.Video)
return streams.OfType<VideoStreamReceiver>().FirstOrDefault();
throw new System.ArgumentException();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b839bc3e2809ef543963ff961d28ce91
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -50,6 +50,26 @@ namespace Unity.RenderStreaming
///
/// </summary>
event Action<string, RTCDataChannel> onAddChannel;
/// <summary>
/// 参与者加入事件 (connectionId, participantId)
/// </summary>
event Action<string, string> onParticipantJoined;
/// <summary>
/// 参与者离开事件 (connectionId, participantId)
/// </summary>
event Action<string, string> onParticipantLeft;
/// <summary>
/// 呼叫请求事件 (connectionId, data)
/// </summary>
event Action<string, string> onCallRequest;
/// <summary>
/// 自定义消息事件 (connectionId, participantId, message)
/// </summary>
event Action<string, string, string> onMessage;
}
public interface IRenderStreamingHandler

View File

@@ -41,4 +41,36 @@ namespace Unity.RenderStreaming
{
void OnAddReceiver(SignalingEventData eventData);
}
/// <summary>
/// 参与者加入事件处理器仅Host收到
/// </summary>
public interface IParticipantJoinedHandler : IEventSystemHandler
{
void OnParticipantJoined(SignalingEventData eventData);
}
/// <summary>
/// 参与者离开事件处理器
/// </summary>
public interface IParticipantLeftHandler : IEventSystemHandler
{
void OnParticipantLeft(SignalingEventData eventData);
}
/// <summary>
/// 呼叫请求事件处理器
/// </summary>
public interface ICallRequestHandler : IEventSystemHandler
{
void OnCallRequest(SignalingEventData eventData);
}
/// <summary>
/// 自定义消息事件处理器
/// </summary>
public interface IMessageHandler : IEventSystemHandler
{
void OnMessage(SignalingEventData eventData);
}
}

View File

@@ -94,6 +94,12 @@ namespace Unity.RenderStreaming.Signaling
public event OnOfferHandler OnOffer;
public event OnAnswerHandler OnAnswer;
public event OnIceCandidateHandler OnIceCandidate;
#pragma warning disable 0067
public event OnParticipantJoinedHandler OnParticipantJoined;
public event OnParticipantLeftHandler OnParticipantLeft;
public event OnCallRequestHandler OnCallRequest;
public event OnMessageHandler OnMessage;
#pragma warning restore 0067
public void SendOffer(string connectionId, RTCSessionDescription offer)
{

View File

@@ -8,6 +8,10 @@ namespace Unity.RenderStreaming.Signaling
public delegate void OnOfferHandler(ISignaling signaling, DescData e);
public delegate void OnAnswerHandler(ISignaling signaling, DescData e);
public delegate void OnIceCandidateHandler(ISignaling signaling, CandidateData e);
public delegate void OnParticipantJoinedHandler(ISignaling signaling, ParticipantEventData e);
public delegate void OnParticipantLeftHandler(ISignaling signaling, ParticipantEventData e);
public delegate void OnCallRequestHandler(ISignaling signaling, CallRequestData e);
public delegate void OnMessageHandler(ISignaling signaling, OnMessageData e);
public interface ISignaling
{
@@ -20,6 +24,10 @@ namespace Unity.RenderStreaming.Signaling
event OnOfferHandler OnOffer;
event OnAnswerHandler OnAnswer;
event OnIceCandidateHandler OnIceCandidate;
event OnParticipantJoinedHandler OnParticipantJoined;
event OnParticipantLeftHandler OnParticipantLeft;
event OnCallRequestHandler OnCallRequest;
event OnMessageHandler OnMessage;
string Url { get; }

View File

@@ -10,6 +10,7 @@ namespace Unity.RenderStreaming
public string sdp;
public bool polite;
public DateTime dateTime;
public string participantId;
}
[Serializable]
@@ -36,6 +37,9 @@ namespace Unity.RenderStreaming
public string candidate;
public string sdpMid;
public int sdpMLineIndex;
public string role;
public string reason;
public string data;
}
[Serializable]
@@ -106,5 +110,36 @@ namespace Unity.RenderStreaming
public string datetime;
}
/// <summary>
/// 参与者加入/离开事件数据
/// </summary>
[Serializable]
public class ParticipantEventData
{
public string connectionId;
public string participantId;
}
/// <summary>
/// 呼叫请求数据
/// </summary>
[Serializable]
public class CallRequestData
{
public string connectionId;
public string data;
}
/// <summary>
/// 自定义消息数据
/// </summary>
[Serializable]
public class OnMessageData
{
public string connectionId;
public string participantId;
public string message;
}
#pragma warning restore 0649
}

View File

@@ -24,6 +24,23 @@ namespace Unity.RenderStreaming.Signaling
public string participantId;
public string Url { get { return m_url; } }
/// <summary>
/// 当前客户端是否为Host角色由服务器在connect响应中分配
/// </summary>
public bool isHost { get; private set; }
/// <summary>
/// Host连接时使用的房间connectionId
/// </summary>
private string m_roomConnectionId;
/// <summary>
/// 参与者连接ID到房间connectionId的映射
/// Key: participantId, Value: roomConnectionId
/// 用于Host向特定Participant发送消息时将内部connectionId还原为服务器格式
/// </summary>
private Dictionary<string, string> m_participantToRoom = new Dictionary<string, string>();
public WebSocketSignaling(SignalingSettings signalingSettings, SynchronizationContext mainThreadContext)
{
if (signalingSettings == null)
@@ -89,46 +106,97 @@ namespace Unity.RenderStreaming.Signaling
public event OnAnswerHandler OnAnswer;
#pragma warning restore 0067
public event OnIceCandidateHandler OnIceCandidate;
public event OnParticipantJoinedHandler OnParticipantJoined;
public event OnParticipantLeftHandler OnParticipantLeft;
public event OnCallRequestHandler OnCallRequest;
public event OnMessageHandler OnMessage;
/// <summary>
/// 判断一个connectionId是否为参与者连接ID而非房间connectionId
/// </summary>
private bool IsParticipantConnectionId(string connectionId)
{
return m_participantToRoom.ContainsKey(connectionId);
}
/// <summary>
/// 获取参与者对应的房间connectionId
/// </summary>
private string GetRoomConnectionId(string participantConnectionId)
{
return m_participantToRoom.TryGetValue(participantConnectionId, out var roomId) ? roomId : participantConnectionId;
}
public void SendOffer(string connectionId, RTCSessionDescription offer)
{
DescData data = new DescData();
data.connectionId = connectionId;
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
// 而不是内部participantIdparticipantId仅通过routedMessage.participantId传递用于目标选择
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
data.sdp = offer.sdp;
data.dateTime = DateTime.Now;
RoutedMessage<DescData> routedMessage = new RoutedMessage<DescData>();
routedMessage.from = connectionId;
// 如果connectionId是参与者ID使用房间connectionId作为from并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
routedMessage.from = GetRoomConnectionId(connectionId);
routedMessage.participantId = connectionId;
}
else
{
routedMessage.from = connectionId;
routedMessage.participantId = participantId;
}
routedMessage.data = data;
routedMessage.type = "offer";
routedMessage.participantId =participantId;
WSSend(routedMessage);
}
public void SendAnswer(string connectionId, RTCSessionDescription answer)
{
DescData data = new DescData();
data.connectionId = connectionId;
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
data.sdp = answer.sdp;
RoutedMessage<DescData> routedMessage = new RoutedMessage<DescData>();
routedMessage.from = connectionId;
// 如果connectionId是参与者ID使用房间connectionId作为from并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
routedMessage.from = GetRoomConnectionId(connectionId);
routedMessage.participantId = connectionId;
}
else
{
routedMessage.from = connectionId;
routedMessage.participantId = participantId;
}
routedMessage.data = data;
routedMessage.type = "answer";
routedMessage.participantId =participantId;
WSSend(routedMessage);
}
public void SendCandidate(string connectionId, RTCIceCandidate candidate)
{
CandidateData data = new CandidateData();
data.connectionId = connectionId;
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
data.candidate = candidate.Candidate;
data.sdpMLineIndex = candidate.SdpMLineIndex.GetValueOrDefault(0);
data.sdpMid = candidate.SdpMid;
RoutedMessage<CandidateData> routedMessage = new RoutedMessage<CandidateData>();
routedMessage.from = connectionId;
// 如果connectionId是参与者ID使用房间connectionId作为from并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
routedMessage.from = GetRoomConnectionId(connectionId);
routedMessage.participantId = connectionId;
}
else
{
routedMessage.from = connectionId;
}
routedMessage.data = data;
routedMessage.type = "candidate";
@@ -137,12 +205,16 @@ namespace Unity.RenderStreaming.Signaling
public void OpenConnection(string connectionId)
{
m_roomConnectionId = connectionId;
this.WSSend($"{{\"type\":\"connect\", \"connectionId\":\"{connectionId}\"}}");
}
public void CloseConnection(string connectionId)
{
this.WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{connectionId}\"}}");
// 如果关闭的是参与者连接,使用房间connectionId发送disconnect
string actualConnectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
m_participantToRoom.Remove(connectionId);
this.WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{actualConnectionId}\"}}");
}
private void WSManage()
@@ -211,28 +283,51 @@ namespace Unity.RenderStreaming.Signaling
if (routedMessage.type == "connect")
{
msg = JsonUtility.FromJson<SignalingMessage>(content);
isHost = msg.role == "host";
participantId = msg.participantId;
m_mainThreadContext.Post(d => OnCreateConnection?.Invoke(this, msg.connectionId, msg.polite), null);
participantId=msg.participantId;
}
else if (routedMessage.type == "disconnect")
{
msg = JsonUtility.FromJson<SignalingMessage>(content);
m_mainThreadContext.Post(d => OnDestroyConnection?.Invoke(this, msg.connectionId), null);
string disconnectConnectionId = msg.connectionId;
// 如果断开的是参与者连接用participantId查找内部connectionId
if (!string.IsNullOrEmpty(routedMessage.participantId) && isHost)
{
disconnectConnectionId = routedMessage.participantId;
m_participantToRoom.Remove(routedMessage.participantId);
}
m_mainThreadContext.Post(d => OnDestroyConnection?.Invoke(this, disconnectConnectionId), null);
}
else if (routedMessage.type == "offer")
{
DescData offer = new DescData();
offer.connectionId = routedMessage.from;
// Host收到带participantId的offer时使用participantId作为内部connectionId
// 这样每个participant会创建独立的PeerConnection
if (!string.IsNullOrEmpty(routedMessage.participantId) && isHost)
{
offer.connectionId = routedMessage.participantId;
m_participantToRoom[routedMessage.participantId] = routedMessage.from ?? m_roomConnectionId;
}
else
{
offer.connectionId = routedMessage.from;
}
offer.sdp = msg.sdp;
offer.polite = msg.polite;
offer.participantId = routedMessage.participantId;
m_mainThreadContext.Post(d => OnOffer?.Invoke(this, offer), null);
}
else if (routedMessage.type == "answer")
{
DescData answer = new DescData
{
connectionId = routedMessage.from,
sdp = msg.sdp
// Host收到带participantId的answer时使用participantId作为内部connectionId
connectionId = !string.IsNullOrEmpty(routedMessage.participantId) && isHost
? routedMessage.participantId
: routedMessage.from,
sdp = msg.sdp,
participantId = routedMessage.participantId
};
m_mainThreadContext.Post(d => OnAnswer?.Invoke(this, answer), null);
}
@@ -240,13 +335,68 @@ namespace Unity.RenderStreaming.Signaling
{
CandidateData candidate = new CandidateData
{
connectionId = routedMessage.@from,
// Host收到带participantId的candidate时使用participantId作为内部connectionId
connectionId = !string.IsNullOrEmpty(routedMessage.participantId) && isHost
? routedMessage.participantId
: routedMessage.@from,
candidate = msg.candidate,
sdpMLineIndex = msg.sdpMLineIndex,
sdpMid = msg.sdpMid
sdpMid = msg.sdpMid,
participantId = routedMessage.participantId
};
m_mainThreadContext.Post(d => OnIceCandidate?.Invoke(this, candidate), null);
}
else if (routedMessage.type == "participant-joined")
{
// Host收到新参与者加入通知
msg = JsonUtility.FromJson<SignalingMessage>(content);
ParticipantEventData participantData = new ParticipantEventData
{
connectionId = msg.connectionId ?? routedMessage.from,
participantId = msg.participantId ?? routedMessage.participantId
};
// 记录参与者映射
if (!string.IsNullOrEmpty(participantData.participantId))
{
m_participantToRoom[participantData.participantId] = participantData.connectionId;
}
RenderStreaming.Logger.Log($"Signaling: Participant joined - connectionId: {participantData.connectionId}, participantId: {participantData.participantId}");
m_mainThreadContext.Post(d => OnParticipantJoined?.Invoke(this, participantData), null);
}
else if (routedMessage.type == "participant-left")
{
// Host/Participant收到参与者离开通知
msg = JsonUtility.FromJson<SignalingMessage>(content);
ParticipantEventData participantData = new ParticipantEventData
{
connectionId = msg.connectionId ?? routedMessage.from,
participantId = msg.participantId ?? routedMessage.participantId
};
m_participantToRoom.Remove(participantData.participantId);
RenderStreaming.Logger.Log($"Signaling: Participant left - connectionId: {participantData.connectionId}, participantId: {participantData.participantId}");
m_mainThreadContext.Post(d => OnParticipantLeft?.Invoke(this, participantData), null);
}
else if (routedMessage.type == "call-request")
{
msg = JsonUtility.FromJson<SignalingMessage>(content);
CallRequestData callData = new CallRequestData
{
connectionId = routedMessage.from,
data = msg.data
};
m_mainThreadContext.Post(d => OnCallRequest?.Invoke(this, callData), null);
}
else if (routedMessage.type == "on-message")
{
msg = JsonUtility.FromJson<SignalingMessage>(content);
OnMessageData messageData = new OnMessageData
{
connectionId = routedMessage.from,
participantId = routedMessage.participantId,
message = msg.message
};
m_mainThreadContext.Post(d => OnMessage?.Invoke(this, messageData), null);
}
else if (routedMessage.type == "error")
{
msg = JsonUtility.FromJson<SignalingMessage>(content);

View File

@@ -28,6 +28,21 @@ namespace Unity.RenderStreaming
/// </summary>
public string sdp { get; set; }
/// <summary>
/// 参与者ID
/// </summary>
public string participantId { get; set; }
/// <summary>
/// 角色 (host/participant)
/// </summary>
public string role { get; set; }
/// <summary>
/// 自定义消息内容
/// </summary>
public string message { get; set; }
/// <summary>
///
/// </summary>

View File

@@ -20,6 +20,10 @@ namespace Unity.RenderStreaming
handler.onGotAnswer += OnGotAnswer;
handler.onAddChannel += OnAddChannel;
handler.onAddTransceiver += OnAddReceiver;
handler.onParticipantJoined += OnParticipantJoined;
handler.onParticipantLeft += OnParticipantLeft;
handler.onCallRequest += OnCallRequest;
handler.onMessage += OnMessage;
}
public bool Subscribe(Component comp)
@@ -137,5 +141,46 @@ namespace Unity.RenderStreaming
};
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.addReceiverHandler);
}
private void OnParticipantJoined(string connectionId, string participantId)
{
var data = new SignalingEventData(EventSystem.current)
{
connectionId = connectionId,
participantId = participantId
};
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.participantJoinedHandler);
}
private void OnParticipantLeft(string connectionId, string participantId)
{
var data = new SignalingEventData(EventSystem.current)
{
connectionId = connectionId,
participantId = participantId
};
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.participantLeftHandler);
}
private void OnCallRequest(string connectionId, string callData)
{
var data = new SignalingEventData(EventSystem.current)
{
connectionId = connectionId,
message = callData
};
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.callRequestHandler);
}
private void OnMessage(string connectionId, string participantId, string message)
{
var data = new SignalingEventData(EventSystem.current)
{
connectionId = connectionId,
participantId = participantId,
message = message
};
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.messageHandler);
}
}
}

View File

@@ -90,6 +90,26 @@ namespace Unity.RenderStreaming
/// </summary>
public event Action<string, RTCDataChannel> onAddChannel;
/// <summary>
/// 参与者加入事件 (connectionId, participantId)
/// </summary>
public event Action<string, string> onParticipantJoined;
/// <summary>
/// 参与者离开事件 (connectionId, participantId)
/// </summary>
public event Action<string, string> onParticipantLeft;
/// <summary>
/// 呼叫请求事件 (connectionId, data)
/// </summary>
public event Action<string, string> onCallRequest;
/// <summary>
/// 自定义消息事件 (connectionId, participantId, message)
/// </summary>
public event Action<string, string, string> onMessage;
private bool _disposed;
private readonly ISignaling _signaling;
private RTCConfiguration _config;
@@ -122,6 +142,10 @@ namespace Unity.RenderStreaming
_signaling.OnOffer += OnOffer;
_signaling.OnAnswer += OnAnswer;
_signaling.OnIceCandidate += OnIceCandidate;
_signaling.OnParticipantJoined += OnParticipantJoinedHandler;
_signaling.OnParticipantLeft += OnParticipantLeftHandler;
_signaling.OnCallRequest += OnCallRequestHandler;
_signaling.OnMessage += OnMessageHandler;
_signaling.Start();
_startCoroutine(WebRTC.WebRTC.Update());
}
@@ -153,6 +177,10 @@ namespace Unity.RenderStreaming
_signaling.OnOffer -= OnOffer;
_signaling.OnAnswer -= OnAnswer;
_signaling.OnIceCandidate -= OnIceCandidate;
_signaling.OnParticipantJoined -= OnParticipantJoinedHandler;
_signaling.OnParticipantLeft -= OnParticipantLeftHandler;
_signaling.OnCallRequest -= OnCallRequestHandler;
_signaling.OnMessage -= OnMessageHandler;
foreach (var pair in _mapConnectionIdAndPeer)
pair.Value.Dispose();
@@ -428,5 +456,30 @@ namespace Unity.RenderStreaming
RTCSessionDescription description = new RTCSessionDescription { type = RTCSdpType.Offer, sdp = e.sdp };
_startCoroutine(pc.OnGotDescription(description, () => onGotOffer?.Invoke(connectionId, e.sdp)));
}
void OnParticipantJoinedHandler(ISignaling signaling, ParticipantEventData e)
{
onParticipantJoined?.Invoke(e.connectionId, e.participantId);
}
void OnParticipantLeftHandler(ISignaling signaling, ParticipantEventData e)
{
// 参与者离开时销毁对应的PeerConnection
if (_mapConnectionIdAndPeer.ContainsKey(e.participantId))
{
DestroyConnection(e.participantId);
}
onParticipantLeft?.Invoke(e.connectionId, e.participantId);
}
void OnCallRequestHandler(ISignaling signaling, CallRequestData e)
{
onCallRequest?.Invoke(e.connectionId, e.data);
}
void OnMessageHandler(ISignaling signaling, OnMessageData e)
{
onMessage?.Invoke(e.connectionId, e.participantId, e.message);
}
}
}