diff --git a/Assets/Script/CopyFontTextMessage.cs b/Assets/Script/CopyFontTextMessage.cs index 734c36d..e8fbce6 100644 --- a/Assets/Script/CopyFontTextMessage.cs +++ b/Assets/Script/CopyFontTextMessage.cs @@ -44,10 +44,13 @@ public class CopyFontTextMessageOrContentSizeFitter : MonoBehaviour } prentRect.sizeDelta = new Vector2(prentRect.sizeDelta.x, screenHeight); } + + + public enum MessageType + { + Text, + Sprite, + } } -public enum MessageType -{ - Text, - Sprite, -} + diff --git a/Assets/Script/Editor.meta b/Assets/Script/Editor.meta new file mode 100644 index 0000000..8164449 --- /dev/null +++ b/Assets/Script/Editor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 57e284d072f7493d92fb63d0477d0352 +timeCreated: 1778581976 \ No newline at end of file diff --git a/Assets/Script/Editor/MessageChannelEditor.cs b/Assets/Script/Editor/MessageChannelEditor.cs new file mode 100644 index 0000000..4e7345f --- /dev/null +++ b/Assets/Script/Editor/MessageChannelEditor.cs @@ -0,0 +1,134 @@ +// Assets/Script/Editor/MessageChannelEditor.cs +using Unity.RenderStreaming; +using UnityEditor; +using UnityEngine; + +namespace RenderStreaming.Editor +{ + [CustomEditor(typeof(MessageChannel))] + public class MessageChannelEditor : UnityEditor.Editor + { + private Vector2 _scrollPos; + private bool _showHistory = true; + private bool _showStats = true; + + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + + var channel = (MessageChannel)target; + + EditorGUILayout.Space(10); + + // --- 连接状态 --- + EditorGUILayout.BeginVertical("HelpBox"); + EditorGUILayout.LabelField("连接状态", EditorStyles.boldLabel); + EditorGUI.indentLevel++; + EditorGUILayout.LabelField("Channel Label", channel.Label); + EditorGUILayout.LabelField("Connection ID", channel.ConnectionId ?? "未连接"); + var stateContent = channel.IsConnected + ? new GUIContent("● 已连接", EditorGUIUtility.FindTexture("greenCheck")) + : new GUIContent("○ 未连接"); + if (channel.IsConnected) + GUI.color = Color.green; + else + GUI.color = Color.gray; + EditorGUILayout.LabelField( stateContent); + GUI.color = Color.white; + EditorGUI.indentLevel--; + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(5); + + // --- 统计信息 --- + if (_showStats) + { + EditorGUILayout.BeginVertical("HelpBox"); + _showStats = EditorGUILayout.BeginToggleGroup("统计信息", _showStats); + EditorGUI.indentLevel++; + EditorGUILayout.LabelField("收到消息总数", channel.ReceivedMessageCount.ToString()); + EditorGUILayout.LabelField("历史记录数", channel.MessageHistory.Count.ToString()); + EditorGUI.indentLevel--; + EditorGUILayout.EndToggleGroup(); + EditorGUILayout.EndVertical(); + } + + EditorGUILayout.Space(5); + + // --- 消息历史 --- + EditorGUILayout.BeginVertical("HelpBox"); + _showHistory = EditorGUILayout.Foldout(_showHistory, "消息历史", true, EditorStyles.boldLabel); + + if (_showHistory) + { + var history = channel.MessageHistory; + + if (history == null || history.Count == 0) + { + EditorGUILayout.HelpBox("暂无消息记录", MessageType.Info); + } + else + { + _scrollPos = EditorGUILayout.BeginScrollView( + _scrollPos, GUILayout.MinHeight(120), GUILayout.MaxHeight(300)); + + for (int i = history.Count - 1; i >= 0; i--) + { + var msg = history[i]; + + // 交替背景色 + if (i % 2 == 0) + { + var bg = new GUIStyle("CN EntryBackEven"); + EditorGUILayout.BeginVertical(bg); + } + else + { + EditorGUILayout.BeginVertical(); + } + + // 方向标签 + 时间 + EditorGUILayout.BeginHorizontal(); + var dirIcon = msg.isSent ? "▶ 发送" : "◀ 接收"; + var dirStyle = msg.isSent + ? new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(0.3f, 0.6f, 1f) } } + : new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(1f, 0.7f, 0.2f) } }; + EditorGUILayout.LabelField(dirIcon, dirStyle, GUILayout.Width(60)); + EditorGUILayout.LabelField(msg.timestamp, GUILayout.Width(70)); + //EditorGUILayout.LabelField(msg.connectionId, EditorStyles.miniLabel); + EditorGUILayout.EndHorizontal(); + + // 消息内容 + EditorGUILayout.SelectableLabel(msg.type, EditorStyles.wordWrappedLabel, + GUILayout.Height(EditorStyles.wordWrappedLabel.CalcHeight( + new GUIContent(msg.type), EditorGUIUtility.currentViewWidth - 40))); + + EditorGUILayout.EndVertical(); + EditorGUILayout.Space(2); + } + + EditorGUILayout.EndScrollView(); + } + + // 清除按钮 + EditorGUILayout.Space(5); + GUI.backgroundColor = new Color(1f, 0.5f, 0.5f); + if (GUILayout.Button("清除消息记录", GUILayout.Height(25))) + { + Undo.RecordObject(channel, "Clear Message History"); + channel.ClearHistory(); + EditorUtility.SetDirty(channel); + } + GUI.backgroundColor = Color.white; + } + + EditorGUILayout.EndVertical(); + + // 持续刷新 Inspector(消息实时到达时自动更新) + if (Application.isPlaying && channel.IsConnected) + { + Repaint(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Script/Editor/MessageChannelEditor.cs.meta b/Assets/Script/Editor/MessageChannelEditor.cs.meta new file mode 100644 index 0000000..afa4706 --- /dev/null +++ b/Assets/Script/Editor/MessageChannelEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a373fd4db0504f8c8e5cfe1f6a964426 +timeCreated: 1778581986 \ No newline at end of file diff --git a/Assets/Script/WebRtc/MessageChannel.cs b/Assets/Script/WebRtc/MessageChannel.cs index c382147..9d8ce1d 100644 --- a/Assets/Script/WebRtc/MessageChannel.cs +++ b/Assets/Script/WebRtc/MessageChannel.cs @@ -1,26 +1,117 @@ // Assets/Script/MessageChannel.cs + using System; +using System.Collections.Generic; using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using UnityEngine; namespace Unity.RenderStreaming { public class MessageChannel : DataChannelBase { - public event Action OnMessageReceived; // connectionId, message + public event Action OnMessageReceived; + public event Action OnMediaStateChangeReceived; - protected override void OnMessage(byte[] bytes) + [Header("消息记录")] [SerializeField, TextArea(1, 3)] + private string lastReceivedMessage; + + [SerializeField] private int receivedMessageCount; + + [SerializeField] private List messageHistory = new List(); + + private const int MAX_HISTORY = 100; + + public IReadOnlyList MessageHistory => messageHistory; + public int ReceivedMessageCount => receivedMessageCount; + + private void Start() + { + label = "on-message"; + } + + public override void OnMessage(string message) { try { - string json = Encoding.UTF8.GetString(bytes); - Debug.Log($"[MessageChannel] Received: {json}"); - OnMessageReceived?.Invoke(ConnectionId, json); + Debug.Log($"[MessageChannel] Received: {message}"); + var record = JsonConvert.DeserializeObject(message); + if (record == null) + { + record = new MessageRecord { type = "raw", data = message }; + } + + JObject json = null; + switch (record.type) + { + case MessageTypes.Chat: + var chat = record.data as ChatData; + break; + case MessageTypes.UserInfo: + json = record.data as JObject; + var info = json.ToObject(); + OnMessageReceived?.Invoke(ConnectionId, info); + break; + case MessageTypes.MediaStateChange: + json = record.data as JObject; + var mediaState = json.ToObject(); + OnMediaStateChangeReceived?.Invoke(ConnectionId, mediaState); + break; + } + + messageHistory.Add(record); + if (messageHistory.Count > MAX_HISTORY) + messageHistory.RemoveAt(0); + + lastReceivedMessage = message; + receivedMessageCount++; } catch (Exception e) { Debug.LogError($"[MessageChannel] Parse error: {e.Message}"); } } + + public void SendMessage(string type, T data) + { + var record = new MessageRecord + { + type = type, + data = JsonConvert.SerializeObject(data) + }; + string json = JsonConvert.SerializeObject(record); + Send(json); + + record.isSent = true; + messageHistory.Add(record); + if (messageHistory.Count > MAX_HISTORY) + messageHistory.RemoveAt(0); + } + + public void SendMessage(string message) + { + Send(message); + var record = new MessageRecord { type = "raw", data = message, isSent = true }; + messageHistory.Add(record); + if (messageHistory.Count > MAX_HISTORY) + messageHistory.RemoveAt(0); + } + + public void ClearHistory() + { + messageHistory.Clear(); + receivedMessageCount = 0; + lastReceivedMessage = ""; + } + + [Serializable] + public class MessageRecord + { + public string type; + public object data; + public bool isSent; + public string timestamp = DateTime.Now.ToString(); + } } } \ No newline at end of file diff --git a/Assets/Script/WebRtc/MessageTypes.cs b/Assets/Script/WebRtc/MessageTypes.cs new file mode 100644 index 0000000..3d48ccb --- /dev/null +++ b/Assets/Script/WebRtc/MessageTypes.cs @@ -0,0 +1,52 @@ +// Assets/Script/WebRtc/MessageTypes.cs +using System; +using Newtonsoft.Json; +using UnityEngine; + +namespace Unity.RenderStreaming +{ + public static class MessageTypes + { + public const string Chat = "chat"; + public const string UserInfo = "user-info"; + public const string MediaStateChange = "media-state-changed"; + public const string Image = "image"; + } + + [Serializable] + public class ChatData + { + public string senderId; + public string senderName; + public string content; + public long timestamp; + } + + [Serializable] + public class UserInfo + { + public string id; + public string name; + public string avatar; + } + + [Serializable] + public class MediaStateChange + { + public string userId; + public bool audio; + public bool video; + public bool screenShare; + public bool recording; + public bool isSpeaking; + } + + [Serializable] + public class ImageData + { + public string senderId; + public string imageUrl; + public int width; + public int height; + } +} \ No newline at end of file diff --git a/Assets/Script/WebRtc/MessageTypes.cs.meta b/Assets/Script/WebRtc/MessageTypes.cs.meta new file mode 100644 index 0000000..953e597 --- /dev/null +++ b/Assets/Script/WebRtc/MessageTypes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb7316441d2d42a1ba12b3b9d02a4e2b +timeCreated: 1778596506 \ No newline at end of file diff --git a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/DataChannelBase.cs b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/DataChannelBase.cs index ff73391..5420ddc 100644 --- a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/DataChannelBase.cs +++ b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/DataChannelBase.cs @@ -119,7 +119,13 @@ namespace Unity.RenderStreaming protected virtual void OnMessage(byte[] bytes) { } - + /// + /// + /// + /// + public virtual void OnMessage(string message) + { + } /// /// /// diff --git a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs index c61faf3..b7ac215 100644 --- a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs +++ b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs @@ -324,6 +324,14 @@ namespace Unity.RenderStreaming public void OnMessage(SignalingEventData eventData) { Debug.Log($"[HostConnection] Message from: {eventData.connectionId}, participantId: {eventData.participantId}, message: {eventData.message}"); + foreach (var channel in streams.OfType().Where(c => c.Label=="on-message")) + { + if (channel != null) + { + channel.OnMessage(eventData.message); + } + } + } /// diff --git a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs index 109ae71..a90cf93 100644 --- a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs +++ b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs @@ -388,13 +388,13 @@ namespace Unity.RenderStreaming.Signaling } else if (routedMessage.type == "on-message") { - msg = JsonUtility.FromJson(content); - OnMessageData messageData = new OnMessageData - { - connectionId = routedMessage.from, - participantId = routedMessage.participantId, - message = msg.message - }; + var message = JsonUtility.FromJson(content); + OnMessageData messageData = new OnMessageData + { + connectionId = routedMessage.from, + participantId = routedMessage.participantId, + message = message.data + }; m_mainThreadContext.Post(d => OnMessage?.Invoke(this, messageData), null); } else if (routedMessage.type == "error")