接入聊天

This commit is contained in:
2026-05-22 10:59:18 +08:00
parent 369783939b
commit 6f17a740e8
11 changed files with 610 additions and 984 deletions

View File

@@ -18,6 +18,11 @@ public interface IGlobalConfigSystem : ISystem
public void StopConnectionTime();
public string GetConnectionStartTime();
public void SetUserCount(int userCount);
public int GetUserCount();
public int GetConnectionTimeType();
public void SetConnectionTimeType(int connectionTimeType);
@@ -45,6 +50,11 @@ public class GlobalConfigSystem : AbstractSystem, IGlobalConfigSystem
/// </summary>
private string _connectionName;
/// <summary>
/// 开始时间
/// </summary>
private string _connectionStartTime;
/// <summary>
/// 连接时间
/// </summary>
@@ -63,6 +73,11 @@ public class GlobalConfigSystem : AbstractSystem, IGlobalConfigSystem
/// </summary>
private string _userId;
/// <summary>
/// 人数
/// </summary>
/// <returns></returns>
private int _userCount;
public override void Dispose()
{
@@ -107,6 +122,7 @@ public class GlobalConfigSystem : AbstractSystem, IGlobalConfigSystem
{
_cts = new CancellationTokenSource();
_connectionTime = 0;
_connectionStartTime = System.DateTime.Now.ToString("HH:mm:ss");
while (!_cts.IsCancellationRequested)
{
_connectionTime += Time.deltaTime;
@@ -124,6 +140,28 @@ public class GlobalConfigSystem : AbstractSystem, IGlobalConfigSystem
return $"{hours:D2}:{minutes:D2}:{seconds:D2}";
}
public string GetConnectionStartTime()
{
if (string.IsNullOrEmpty(_connectionStartTime))
{
Debug.LogWarning("GlobalConfigSystem: GetConnectionStartTime not set");
return "";
}
return _connectionStartTime;
}
public void SetUserCount(int userCount)
{
_userCount = userCount;
}
public int GetUserCount()
{
return _userCount;
}
public void StopConnectionTime()
{
_cts?.Cancel();

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Script.Util;
using Stary.Evo;
using Stary.Evo.UIFarme;
using UnityEngine;
@@ -43,6 +44,8 @@ namespace Script
/// </summary>
private Text _roomPeopleNumText;
private Transform _userGrid;
/// <summary>
/// 时间
/// </summary>
@@ -57,6 +60,10 @@ namespace Script
public override string UIPath => "Canvas";
public Action<List<UsersItem>> OnUsersChangedEvnent;
private GameObjectPool _objectPool;
public override void Initialize(GameObject panelGo)
{
base.Initialize(panelGo);
@@ -65,6 +72,8 @@ namespace Script
_arrowLeft = panelGo.transform.Find("Header/arrow-left").GetComponent<Button>();
_idText = panelGo.transform.Find("MeetingInfoCard/meeting/id").GetComponent<Text>();
_roomPeopleNumText = panelGo.transform.Find("MeetingInfoCard/numberOfPeople/number").GetComponent<Text>();
_userGrid = panelGo.transform.Find("MeetingInfoCard/userGrid");
_objectPool = panelGo.transform.Find("MeetingInfoCard/pool").GetComponent<GameObjectPool>();
_chatTog = panelGo.transform.Find("Tabs/Chat").GetComponent<Toggle>();
_contactsTog = panelGo.transform.Find("Tabs/Contacts").GetComponent<Toggle>();
_meetingOrganizersTog = panelGo.transform.Find("Tabs/MeetingOrganizers").GetComponent<Toggle>();
@@ -72,23 +81,25 @@ namespace Script
_meetingContacts = new MeetingContacts();
_meetingContacts.Initialize(panelGo.transform.Find("MeetingContacts").gameObject);
_meetingInfoList = new MeetingInfoList();
_meetingInfoList.Initialize(panelGo.transform.Find("MeetingInfoList").gameObject);
_meetingInfoList.Initialize(panelGo.transform.Find("MeetingInfoList").gameObject, this);
_meetingChat = new MeetingChat();
_meetingChat.Initialize(panelGo.transform.Find("MeetingChat").gameObject);
_meetingChat.Initialize(panelGo.transform.Find("MeetingChat").gameObject, this);
}
public override void OnEnter(Action complete = null)
{
base.OnEnter(complete);
_meetingInfoList.OnEnter();
;
_titleText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionName();
this.GetSystem<IGlobalConfigSystem>().StartConnectionTime(_timeText);
_idText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionId();
_arrowLeft.onClick.AddListener(OnArrowLeftClick);
_chatTog.onValueChanged.AddListener(OnChatTog);
_contactsTog.onValueChanged.AddListener(OnContactsTog);
_meetingOrganizersTog.onValueChanged.AddListener(OnMeetingOrganizersTog);
OnUsersChangedEvnent += OnUsersChanged;
}
@@ -97,10 +108,28 @@ namespace Script
base.OnExit(delay);
_meetingContacts.OnExit();
_meetingInfoList.OnExit();
_meetingChat.OnExit();
_arrowLeft.onClick.RemoveListener(OnArrowLeftClick);
_chatTog.onValueChanged.RemoveListener(OnChatTog);
_contactsTog.onValueChanged.RemoveListener(OnContactsTog);
_meetingOrganizersTog.onValueChanged.RemoveListener(OnMeetingOrganizersTog);
OnUsersChangedEvnent += OnUsersChanged;
}
private async void OnUsersChanged(List<UsersItem> obj)
{
for (var i = 0; i < _objectPool.transform.childCount; i++)
_objectPool.Release(_objectPool.transform.GetChild(i).gameObject);
_roomPeopleNumText.text = obj.Count.ToString();
for (var i = 0; i < obj.Count; i++)
{
var entry = _objectPool.Get();
await WebRTCUtil.DownloadAndSetAvatar(obj[i].avatar,
entry.transform.Find("image").GetComponent<Image>());
}
// 更新会议聊天面板人数
_meetingChat.OnUserCountChangedEvent?.Invoke(obj.Count);
}
private void OnMeetingOrganizersTog(bool value)
@@ -117,6 +146,7 @@ namespace Script
private void OnChatTog(bool value)
{
_meetingChat.PanelGo.SetActive(value);
if (value) _meetingChat.OnEnter();
}
private void OnArrowLeftClick()

View File

@@ -1,24 +1,105 @@
using System;
using System.Collections.Generic;
using RenderStreaming;
using Script.Util;
using Stary.Evo;
using Unity.RenderStreaming;
using UnityEngine;
using UnityEngine.UI;
namespace Script
{
public class MeetingChat : IController
{
public GameObject PanelGo;
private MainPanel _mainPanel;
public void Initialize(GameObject panelGo)
private Transform _content;
private GameObjectPool _objectRightPool;
private GameObjectPool _objectLeftPool;
private Text _connectionTimeText;
private Text _userCountText;
public Action<int> OnUserCountChangedEvent;
private List<ChatData> _chatDatas = new();
public void Initialize(GameObject panelGo, MainPanel mainPanel)
{
PanelGo = panelGo;
_mainPanel = mainPanel;
_content = panelGo.transform.Find("MeetingGrid/Viewport/Content");
_objectRightPool = panelGo.transform.Find("MeetingGrid/LeftPool").GetComponent<GameObjectPool>();
_objectLeftPool = panelGo.transform.Find("MeetingGrid/RightPool").GetComponent<GameObjectPool>();
_connectionTimeText = panelGo.transform.Find("MeetingNum/Time").GetComponent<Text>();
_connectionTimeText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionStartTime();
_userCountText = panelGo.transform.Find("MeetingNum/Num").GetComponent<Text>();
_userCountText.text = this.GetSystem<IGlobalConfigSystem>().GetUserCount().ToString();
}
public async void OnEnter()
{
OnUserCountChangedEvent += OnUserCountChanged;
GameObject.FindObjectOfType<MessageChannel>().OnChatMessageReceived += OnChatMessageReceivedEvent;
}
public async void OnExit()
{
OnUserCountChangedEvent -= OnUserCountChanged;
GameObject.FindObjectOfType<MessageChannel>().OnChatMessageReceived -= OnChatMessageReceivedEvent;
}
private void OnChatMessageReceivedEvent(string connectionId, ChatData data)
{
if (connectionId != this.GetSystem<IGlobalConfigSystem>().GetConnectionId()) return;
_chatDatas.Add(data);
if (bool.Parse(data.isSelf) == false)
{
var entry = _objectLeftPool.Get();
SetMessageEntry(data, entry);
}
}
private void SetMessageEntry(ChatData data, GameObject entry)
{
var head = entry.transform.Find("head");
var name = entry.transform.Find("name");
var message = entry.transform.Find("message");
var sprite = entry.transform.Find("sprite");
if (string.IsNullOrEmpty(data.senderAvatar))
{
var randomColor = WebRTCUtil.GetRandomColor();
head.GetComponent<Image>().color = randomColor;
head.transform.Find("Name").GetComponent<Text>().text = data.senderName.Substring(0, 1);
}
else
{
WebRTCUtil.DownloadAndSetAvatar(data.senderAvatar, head.GetComponent<Image>());
}
name.GetComponent<Text>().text = data.senderName;
if (data.type == "text")
{
message.GetComponent<Text>().text = data.content;
sprite.gameObject.SetActive(false);
}
else if (data.type == "image")
{
message.gameObject.SetActive(false);
sprite.gameObject.SetActive(true);
//TODO 图片传输功能
}
}
private void OnUserCountChanged(int obj)
{
_userCountText.text = obj.ToString();
}
public IArchitecture GetArchitecture()

View File

@@ -10,6 +10,7 @@ namespace Script
{
public class MeetingInfoList : IController
{
private MainPanel _mainPanel;
public GameObject PanelGo;
/// <summary>
@@ -28,9 +29,10 @@ namespace Script
private GameObjectPool _objectPool;
public void Initialize(GameObject panelGo)
public void Initialize(GameObject panelGo, MainPanel mainPanel)
{
PanelGo = panelGo;
_mainPanel = mainPanel;
_contactEntryPrefab = Resources.Load<GameObject>("ParticipantEntry");
_content = panelGo.transform.Find("MeetingGrid/Viewport/Content");
_meetingNum = panelGo.transform.Find("MeetingNum/Num").GetComponent<Text>();
@@ -103,6 +105,8 @@ namespace Script
$"/signaling/users?connectionId={this.GetSystem<IGlobalConfigSystem>().GetConnectionId()}");
if (response != null && response.totalCount > 0)
{
this.GetSystem<IGlobalConfigSystem>().SetUserCount(response.totalCount);
_mainPanel.OnUsersChangedEvnent?.Invoke(response.users);
_meetingNum.text = response.totalCount.ToString();
for (var i = 0; i < response.totalCount; i++)
{

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
using UnityEngine.UI;
@@ -9,6 +11,8 @@ namespace Script.Util
{
public static class WebRTCUtil
{
public static Dictionary<string, Sprite> _avatarCache = new();
public static Color GetRandomColor()
{
return new Color(
@@ -19,10 +23,16 @@ namespace Script.Util
);
}
public static async void DownloadAndSetAvatar(string avatarUrl, Image targetImage)
public static async UniTask DownloadAndSetAvatar(string avatarUrl, Image targetImage)
{
try
{
if (_avatarCache.TryGetValue(avatarUrl, out var sprite))
{
targetImage.sprite = sprite;
return;
}
var tempPath = Path.Combine(Application.temporaryCachePath, $"avatar_{Guid.NewGuid()}.png");
var result = await WebRequestSystem.GetFile(avatarUrl, tempPath);
@@ -32,11 +42,12 @@ namespace Script.Util
var texture = new Texture2D(2, 2);
texture.LoadImage(bytes);
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
Vector2.one * 0.5f);
targetImage.sprite = sprite;
File.Delete(tempPath);
_avatarCache.TryAdd(avatarUrl, sprite);
}
}
catch (Exception e)

View File

@@ -29,6 +29,7 @@ namespace Unity.RenderStreaming
public event Action<string, UserInfo> OnUserInfoMessageReceived;
public event Action<string, MediaStateChange> OnMediaStateChangeReceived;
public event Action<string, ChatData> OnChatMessageReceived;
public override void OnMessage(string message)
@@ -44,7 +45,9 @@ namespace Unity.RenderStreaming
switch (record.type)
{
case MessageTypes.Chat:
var chat = record.data as ChatData;
var chat = record.data as JObject;
var chatData = chat.ToObject<ChatData>();
OnChatMessageReceived?.Invoke(ConnectionId, chatData);
break;
case MessageTypes.UserInfo:
json = record.data as JObject;

View File

@@ -9,7 +9,7 @@ namespace Unity.RenderStreaming
{
public static class MessageTypes
{
public const string Chat = "chat";
public const string Chat = "chat-message";
public const string UserInfo = "user-info";
public const string MediaStateChange = "media-state-changed";
public const string ParticipantsSync = "participants-sync";
@@ -18,10 +18,14 @@ namespace Unity.RenderStreaming
[Serializable]
public class ChatData
{
public string id;
public string senderId;
public string senderName;
public string senderAvatar;
public string content;
public long timestamp;
public string type;
public string timestamp;
public string isSelf;
}
[Serializable]