using UnityEngine; using UnityEngine.UI; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Collections.Generic; using System; public class DisplayServer : MonoBehaviour { private TcpListener listener; // 用于接受客户端连接的TCP监听器 private Thread listenThread; // 用于接受客户端连接的线程 private CancellationTokenSource listenCts = new CancellationTokenSource(); // 控制线程取消 private volatile bool isRunning = true; // 线程安全的服务器循环标志 private NetworkStream clientStream; // 当前客户端的网络流,用于发送消息 public Transform background; // UI页面的父级变换(BG,包含Image组件) [System.Serializable] public class PageModel { public string pageName; // 页面名称 public GameObject model; // 与页面关联的模型(挂载ModelController) } public List pageModels = new List(); // 页面-模型映射列表 private readonly Queue messageQueue = new Queue(); // 线程安全的消息队列 private readonly object queueLock = new object(); // 消息队列访问锁 private string currentPage = ""; // 跟踪当前显示的页面 private Dictionary pageModelCache; // 页面-模型映射的缓存 private bool isPlayingAnimation = false; // 跟踪动画播放状态 private bool isClientDragging = false; // 跟踪客户端是否正在拖动Slider private float lastSendTime = 0f; // 上次发送进度的时间 private float sendInterval = 0.05f; // 进度发送间隔(秒) private float lastSentProgress = 0f; // 记录上次发送的进度 [Header("Background Sprites")] public Sprite textBackgroundSprite; // 有文字时的背景Sprite public Sprite noTextBackgroundSprite; // 无文字时的背景Sprite // 脚本启动时调用 void Start() { // 设置显示端分辨率为 3328x1352 Screen.SetResolution(3328, 1352, false); // 初始化页面-模型缓存以加快查找 pageModelCache = new Dictionary(); foreach (var pm in pageModels) { if (!string.IsNullOrEmpty(pm.pageName) && pm.model != null) { pageModelCache[pm.pageName] = pm; } else { Debug.LogWarning($"PageModel 配置错误: pageName={pm.pageName}, model={(pm.model != null ? pm.model.name : "null")}"); } } // 在端口8888上启动TCP监听 try { listener = new TcpListener(IPAddress.Any, 8888); listener.Start(); Debug.Log("TCP监听启动成功,端口: 8888"); } catch (Exception ex) { Debug.LogError($"TCP监听启动失败: {ex.Message}"); return; } // 启动线程以监听客户端连接 listenThread = new Thread(() => ListenForClients(listenCts.Token)); listenThread.Start(); Debug.Log("显示端服务器已启动,等待触摸端连接..."); // 显示初始页面 ShowPage("首页"); } // 监听传入的TCP客户端连接 private void ListenForClients(CancellationToken token) { while (!token.IsCancellationRequested && isRunning) { try { TcpClient client = listener.AcceptTcpClient(); Debug.Log($"触摸端已连接!客户端地址: {((IPEndPoint)client.Client.RemoteEndPoint).Address}"); clientStream = client.GetStream(); // 保存客户端流以发送消息 // 为每个客户端启动新线程处理通信 Thread clientThread = new Thread(() => HandleClientComm(client, token)); clientThread.Start(); } catch (Exception ex) { Debug.LogError($"接受客户端连接错误: {ex.Message}"); Thread.Sleep(2000); // 等待2秒重试 } } } // 处理与单个客户端的通信 private void HandleClientComm(TcpClient tcpClient, CancellationToken token) { NetworkStream stream = tcpClient.GetStream(); byte[] message = new byte[4096]; int bytesRead; // 在未取消或未断开连接的情况下持续读取 while (!token.IsCancellationRequested && isRunning) { try { bytesRead = stream.Read(message, 0, 4096); if (bytesRead == 0) break; // 客户端断开连接 string data = Encoding.UTF8.GetString(message, 0, bytesRead); lock (queueLock) { messageQueue.Enqueue(data); // 将消息加入队列以供处理 } } catch (Exception ex) { Debug.LogError($"读取客户端消息错误: {ex.Message}"); break; } } // 清理客户端资源 stream.Close(); tcpClient.Close(); clientStream = null; // 清空客户端流 Debug.Log("客户端断开连接"); } // 在主线程中处理排队的消息并发送动画进度 private void Update() { // 处理接收到的消息 string msg = null; lock (queueLock) { if (messageQueue.Count > 0) { msg = messageQueue.Dequeue(); // 获取下一条消息 } } if (!string.IsNullOrEmpty(msg)) { Debug.Log($"收到消息: {msg}"); if (msg.StartsWith("Page:")) { string pageName = msg.Replace("Page:", ""); ShowPage(pageName); isPlayingAnimation = false; // 重置播放状态 isClientDragging = false; // 重置拖动状态 lastSentProgress = 0f; // 重置进度 } else if (msg.StartsWith("Model:")) { string modelName = msg.Replace("Model:", ""); PlayModelAnimation(modelName); lastSentProgress = 0f; // 重置进度 } else if (msg.StartsWith("Progress:")) { if (float.TryParse(msg.Replace("Progress:", ""), out float progress)) { SetAnimationProgress(progress); isPlayingAnimation = false; // 拖动时停止播放 isClientDragging = true; // 标记客户端正在拖动 lastSentProgress = progress; // 更新最后发送的进度 Debug.Log($"处理进度消息: Progress:{progress:F2}"); } } else if (msg == "EndDrag") { isClientDragging = false; // 客户端拖动结束 Debug.Log("客户端Slider拖动结束"); } else if (msg.StartsWith("TextPanel:")) { string command = msg.Replace("TextPanel:", ""); SetTextPanelVisibility(command == "Show"); Debug.Log($"处理文字面板消息: {msg}"); } else if (msg.StartsWith("Background:")) { string command = msg.Replace("Background:", ""); SetBackgroundSprite(command == "Text"); Debug.Log($"处理背景消息: {msg}"); } } // 仅当动画播放且客户端未拖动时发送进度,且限制发送频率 if (isPlayingAnimation && !isClientDragging && clientStream != null && clientStream.CanWrite) { if (Time.time - lastSendTime >= sendInterval) { if (pageModelCache.TryGetValue(currentPage, out PageModel pm) && pm != null && pm.model != null) { ModelController mc = pm.model.GetComponent(); if (mc != null && mc.IsPlayingAnimation()) { float progress = mc.GetAnimationProgress(); // 仅当进度有效且变化显著时发送 if (progress > 0f && Mathf.Abs(progress - lastSentProgress) > 0.005f) { try { string progressMsg = $"Progress:{progress:F2}"; byte[] data = Encoding.UTF8.GetBytes(progressMsg); clientStream.Write(data, 0, data.Length); Debug.Log($"发送动画进度: {progressMsg}"); lastSentProgress = progress; // 更新最后发送的进度 lastSendTime = Time.time; // 更新发送时间 } catch (Exception ex) { Debug.LogError($"发送动画进度失败: {ex.Message}"); clientStream = null; // 标记流失效 } } } else { // 动画已停止,更新状态 isPlayingAnimation = false; } } } } } // 切换激活的UI页面并更新模型 private void ShowPage(string pageName) { if (background == null) { Debug.LogError("背景Transform未设置"); return; } foreach (Transform child in background) { bool isActive = child.name == pageName; child.gameObject.SetActive(isActive); Debug.Log($"页面 {child.name} 设置为 {(isActive ? "激活" : "非激活")}"); } currentPage = pageName; // 更新模型可见性并重置动画 foreach (var pageModel in pageModels) { if (pageModel.model != null) { bool isActive = pageModel.pageName == pageName; pageModel.model.SetActive(isActive); ModelController mc = pageModel.model.GetComponent(); if (mc != null) { // 取消订阅旧事件 mc.OnAnimationFinished -= OnModelAnimationFinished; // 订阅动画结束事件 if (isActive) { mc.OnAnimationFinished += OnModelAnimationFinished; } mc.ResetAnimation(); Debug.Log($"模型 {pageModel.model.name} 重置,页面: {pageName}"); } else { Debug.LogWarning($"模型 {pageModel.model.name} 未找到ModelController"); } } } // 初始化文字面板为显示 SetTextPanelVisibility(true); // 初始化背景为有文字背景 SetBackgroundSprite(true); Debug.Log($"显示端切换到页面: {pageName}"); } // 为指定模型播放动画 private void PlayModelAnimation(string modelName) { PageModel pm = pageModels.Find(p => p.model != null && p.model.name == modelName); if (pm != null) { ModelController mc = pm.model.GetComponent(); if (mc != null) { // 取消旧订阅,添加新订阅 mc.OnAnimationFinished -= OnModelAnimationFinished; mc.OnAnimationFinished += OnModelAnimationFinished; mc.PlayAnimation(); isPlayingAnimation = true; // 确认动画开始播放 Debug.Log($"播放模型动画: {modelName}"); } else { isPlayingAnimation = false; // 动画未启动 Debug.LogWarning($"模型 {modelName} 未找到ModelController"); } } else { isPlayingAnimation = false; // 动画未启动 Debug.LogWarning($"未找到模型 {modelName}"); } } // 设置当前页面模型的动画进度 private void SetAnimationProgress(float progress) { if (pageModelCache.TryGetValue(currentPage, out PageModel pm) && pm != null && pm.model != null) { ModelController mc = pm.model.GetComponent(); if (mc != null) { mc.SetAnimationProgress(progress); Debug.Log($"设置模型 {pm.model.name} 进度: {progress:F2}"); } else { Debug.LogWarning($"模型 {pm.model.name} 未找到ModelController"); } } else { Debug.LogWarning($"未找到页面 {currentPage} 的模型或ModelController"); } } // 设置当前页面文字面板的显隐 private void SetTextPanelVisibility(bool isVisible) { if (background == null || string.IsNullOrEmpty(currentPage) || currentPage == "首页") { Debug.Log($"跳过文字面板显隐设置: background={(background != null ? "存在" : "null")}, currentPage={currentPage}"); return; } Transform pageTransform = background.Find(currentPage); if (pageTransform != null) { Transform textPanel = pageTransform.Find("ItemInfo/TextPanel"); if (textPanel != null) { textPanel.gameObject.SetActive(isVisible); Debug.Log($"设置页面 {currentPage} 文字面板显隐: {isVisible}"); } else { Debug.LogWarning($"未在页面 {currentPage}/ItemInfo 找到TextPanel"); // 尝试递归查找 textPanel = FindDeep(pageTransform, "TextPanel"); if (textPanel != null) { textPanel.gameObject.SetActive(isVisible); Debug.Log($"通过递归查找设置页面 {currentPage} 文字面板显隐: {isVisible}"); } else { Debug.LogWarning($"递归查找仍未找到 {currentPage}/TextPanel"); Debug.Log($"页面 {currentPage} 子物体: {string.Join(", ", GetChildNames(pageTransform))}"); Transform itemInfo = pageTransform.Find("ItemInfo"); if (itemInfo != null) { Debug.Log($"ItemInfo 子物体: {string.Join(", ", GetChildNames(itemInfo))}"); } else { Debug.LogWarning($"未在页面 {currentPage} 找到ItemInfo"); } } } } else { Debug.LogWarning($"未找到页面 {currentPage},背景Transform子物体: {string.Join(", ", GetChildNames(background))}"); } } // 设置公共背景的Sprite private void SetBackgroundSprite(bool hasText) { if (background == null) { Debug.LogError($"背景Transform未设置,无法切换背景"); return; } Image backgroundImage = background.GetComponent(); if (backgroundImage != null) { Sprite newSprite = hasText ? textBackgroundSprite : noTextBackgroundSprite; if (newSprite != null) { backgroundImage.sprite = newSprite; Debug.Log($"设置公共背景: {newSprite.name}"); } else { Debug.LogWarning($"背景Sprite未设置: hasText={hasText}"); } } else { Debug.LogWarning($"BG GameObject未找到Image组件"); Debug.Log($"BG 子物体: {string.Join(", ", GetChildNames(background))}"); } } // 辅助方法:获取Transform的子物体名称 private string[] GetChildNames(Transform parent) { List names = new List(); foreach (Transform child in parent) { names.Add(child.name); } return names.ToArray(); } // 辅助方法:递归查找子物体 private Transform FindDeep(Transform parent, string name) { Transform result = parent.Find(name); if (result != null) return result; foreach (Transform child in parent) { result = FindDeep(child, name); if (result != null) return result; } return null; } // 处理动画结束事件 private void OnModelAnimationFinished() { isPlayingAnimation = false; Debug.Log("模型动画播放完成,停止发送进度"); // 发送最终进度 1.0 if (clientStream != null && clientStream.CanWrite) { try { string progressMsg = "Progress:1.00"; byte[] data = Encoding.UTF8.GetBytes(progressMsg); clientStream.Write(data, 0, data.Length); Debug.Log($"发送最终动画进度: {progressMsg}"); lastSentProgress = 1f; lastSendTime = Time.time; } catch (Exception ex) { Debug.LogError($"发送最终进度失败: {ex.Message}"); clientStream = null; } } } // 应用程序退出时清理资源 private void OnApplicationQuit() { isRunning = false; listenCts.Cancel(); listener.Stop(); clientStream?.Close(); // 取消所有动画结束事件订阅 foreach (var pm in pageModels) { if (pm.model != null) { ModelController mc = pm.model.GetComponent(); if (mc != null) { mc.OnAnimationFinished -= OnModelAnimationFinished; } } } if (listenThread != null && listenThread.IsAlive) { listenThread.Join(1000); // 等待线程结束 } Debug.Log("显示端服务器已停止"); } }