diff --git a/Assets/Scripts/DisplayServer.cs b/Assets/Scripts/DisplayServer.cs index bb6bf25..2063580 100644 --- a/Assets/Scripts/DisplayServer.cs +++ b/Assets/Scripts/DisplayServer.cs @@ -29,6 +29,11 @@ public class DisplayServer : MonoBehaviour 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; // 记录上次发送的进度 // 脚本启动时调用 void Start() @@ -136,42 +141,68 @@ public class DisplayServer : MonoBehaviour { 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拖动结束"); + } } - // 每帧发送动画进度到客户端 - if (clientStream != null && clientStream.CanWrite) + // 仅当动画播放且客户端未拖动时发送进度,且限制发送频率 + if (isPlayingAnimation && !isClientDragging && clientStream != null && clientStream.CanWrite) { - if (pageModelCache.TryGetValue(currentPage, out PageModel pm) && pm != null && pm.model != null) + if (Time.time - lastSendTime >= sendInterval) { - ModelController mc = pm.model.GetComponent(); - if (mc != null) + if (pageModelCache.TryGetValue(currentPage, out PageModel pm) && pm != null && pm.model != null) { - float progress = mc.GetAnimationProgress(); - try + ModelController mc = pm.model.GetComponent(); + if (mc != null && mc.IsPlayingAnimation()) { - string progressMsg = $"Progress:{progress:F2}"; - byte[] data = Encoding.UTF8.GetBytes(progressMsg); - clientStream.Write(data, 0, data.Length); - Debug.Log($"发送动画进度: {progressMsg}"); + 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; // 标记流失效 + } + } } - catch (Exception ex) + else { - Debug.LogError($"发送动画进度失败: {ex.Message}"); - clientStream = null; // 标记流失效 + // 动画已停止,更新状态 + isPlayingAnimation = false; } } } @@ -199,6 +230,13 @@ public class DisplayServer : MonoBehaviour ModelController mc = pageModel.model.GetComponent(); if (mc != null) { + // 取消订阅旧事件 + mc.OnAnimationFinished -= OnModelAnimationFinished; + // 订阅动画结束事件 + if (isActive) + { + mc.OnAnimationFinished += OnModelAnimationFinished; + } mc.ResetAnimation(); Debug.Log($"模型 {pageModel.model.name} 重置,页面: {pageName}"); } @@ -216,9 +254,23 @@ public class DisplayServer : MonoBehaviour 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}"); } } @@ -240,6 +292,31 @@ public class DisplayServer : MonoBehaviour } } + // 处理动画结束事件 + 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() { @@ -248,6 +325,19 @@ public class DisplayServer : MonoBehaviour 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); // 等待线程结束 diff --git a/Assets/Scripts/ModelController.cs b/Assets/Scripts/ModelController.cs index 3b166ae..5dfc3a3 100644 --- a/Assets/Scripts/ModelController.cs +++ b/Assets/Scripts/ModelController.cs @@ -1,5 +1,6 @@ using UnityEngine; using System.Collections.Generic; +using System; public class ModelController : MonoBehaviour { @@ -8,9 +9,15 @@ public class ModelController : MonoBehaviour private bool isPlaying = false; // 跟踪动画播放状态 [Header("默认动画状态名称")] - public string defaultAnimName = "Idle"; // 默认动画状态名称 + public string defaultAnimName = "Take 001"; // 默认动画状态名称 private Dictionary stateHashes = new Dictionary(); // 动画状态哈希缓存 + private float lastLoggedProgress = -1f; // 记录上次日志的进度值 + private float lastWarningTime = 0f; // 记录上次警告日志时间 + private const float warningInterval = 1f; // 警告日志间隔(秒) + + // 动画结束事件 + public event Action OnAnimationFinished; // 脚本初始化时调用 void Awake() @@ -28,12 +35,18 @@ public class ModelController : MonoBehaviour { if (isPlaying && animator != null && !string.IsNullOrEmpty(currentAnim)) { + if (!animator.enabled) + { + animator.enabled = true; // 确保Animator启用 + Debug.Log($"重新启用Animator: {currentAnim}"); + } AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); if (stateInfo.IsName(currentAnim) && stateInfo.normalizedTime >= 1f) { // 动画播放完成,暂停并标记 animator.enabled = false; isPlaying = false; + OnAnimationFinished?.Invoke(); // 通知动画结束 Debug.Log($"动画 {currentAnim} 播放完成,暂停"); } } @@ -80,12 +93,13 @@ public class ModelController : MonoBehaviour return; } + // 停止播放状态 + isPlaying = false; animator.enabled = true; float clampedTime = Mathf.Clamp01(normalizedTime); animator.Play(currentAnim, 0, clampedTime); // 设置动画到指定时间 animator.Update(0f); // 强制立即更新 animator.enabled = false; // 暂停动画 - isPlaying = false; // 标记动画暂停 Debug.Log($"设置动画 {currentAnim} 进度: {clampedTime:F2}"); } @@ -115,13 +129,23 @@ public class ModelController : MonoBehaviour /// 当前动画进度,若无动画则返回0 public float GetAnimationProgress() { - if (animator == null || string.IsNullOrEmpty(currentAnim) || !gameObject.activeSelf) + if (animator == null || !animator.enabled || string.IsNullOrEmpty(currentAnim) || !gameObject.activeSelf) { + if (Time.time - lastWarningTime >= warningInterval) + { + Debug.LogWarning($"无法获取动画进度: animator={animator}, enabled={animator?.enabled}, currentAnim={currentAnim}, active={gameObject.activeSelf}"); + lastWarningTime = Time.time; + } return 0f; } if (!AnimatorHasState(currentAnim)) { + if (Time.time - lastWarningTime >= warningInterval) + { + Debug.LogWarning($"Animator上不存在状态: {currentAnim}"); + lastWarningTime = Time.time; + } return 0f; } @@ -129,9 +153,19 @@ public class ModelController : MonoBehaviour if (stateInfo.IsName(currentAnim)) { float progress = Mathf.Clamp01(stateInfo.normalizedTime % 1f); - Debug.Log($"获取动画 {currentAnim} 进度: {progress:F2}"); + // 仅当进度变化超过0.01时记录日志 + if (Mathf.Abs(progress - lastLoggedProgress) > 0.01f) + { + Debug.Log($"获取动画 {currentAnim} 进度: {progress:F2}"); + lastLoggedProgress = progress; + } return progress; } + if (Time.time - lastWarningTime >= warningInterval) + { + Debug.LogWarning($"动画状态不匹配: currentAnim={currentAnim}, state={stateInfo.fullPathHash}"); + lastWarningTime = Time.time; + } return 0f; } @@ -147,4 +181,10 @@ public class ModelController : MonoBehaviour } return false; } + + // 获取动画播放状态 + public bool IsPlayingAnimation() + { + return isPlaying; + } } \ No newline at end of file diff --git a/Assets/Scripts/TouchClient.cs b/Assets/Scripts/TouchClient.cs index 2401243..718eac6 100644 --- a/Assets/Scripts/TouchClient.cs +++ b/Assets/Scripts/TouchClient.cs @@ -26,6 +26,7 @@ public class TouchClient : MonoBehaviour private readonly Queue progressQueue = new Queue(); // 线程安全的进度队列 private readonly object queueLock = new object(); // 进度队列访问锁 private bool isDraggingSlider = false; // 标记是否正在拖动Slider + private float lastSentProgress = 0f; // 记录最后发送的进度 // 脚本启动时调用 void Start() @@ -110,7 +111,6 @@ public class TouchClient : MonoBehaviour { lock (queueLock) { - progressQueue.Clear(); // 清空队列以确保最新进度 progressQueue.Enqueue(progress); // 将进度加入队列 Debug.Log($"收到进度: {progress:F2}"); } @@ -154,6 +154,24 @@ public class TouchClient : MonoBehaviour // 模型播放按钮点击时调用 public void OnButtonClick_PlayModel(string modelName) { + // 清空进度队列,防止旧进度干扰 + lock (queueLock) + { + progressQueue.Clear(); + } + + // 重置Slider到0 + Slider slider = GetCurrentPageSlider(); + if (slider != null) + { + var onValueChanged = slider.onValueChanged; + slider.onValueChanged = new Slider.SliderEvent(); + slider.value = 0f; + slider.onValueChanged = onValueChanged; + lastSentProgress = 0f; // 重置最后发送的进度 + Debug.Log($"播放模型 {modelName} 前重置Slider到0"); + } + SendMessageToServer("Model:" + modelName); // 通知服务器播放模型 } @@ -162,14 +180,30 @@ public class TouchClient : MonoBehaviour { isDraggingSlider = true; // 标记正在拖动 float progress = slider.value / 100f; // 转换为0-1 - SendMessageToServer("Progress:" + progress.ToString("F2")); // 发送进度 - Debug.Log($"Slider拖动到: {progress:F2}"); + if (progress > 0.01f) // 忽略接近0的值以避免异常 + { + SendMessageToServer("Progress:" + progress.ToString("F2")); // 发送进度 + lastSentProgress = progress; // 记录最后发送的进度 + Debug.Log($"Slider拖动到: {progress:F2}"); + } } // 滑块拖动结束时调用(需在Inspector中绑定) public void OnSliderEndDrag() { + Slider slider = GetCurrentPageSlider(); + if (slider != null) + { + float progress = slider.value / 100f; + if (progress > 0.01f) + { + SendMessageToServer("Progress:" + progress.ToString("F2")); // 发送最终进度 + lastSentProgress = progress; // 更新最后发送的进度 + Debug.Log($"Slider拖动结束,发送最终进度: {progress:F2}"); + } + } isDraggingSlider = false; // 结束拖动 + SendMessageToServer("EndDrag"); // 通知服务器拖动结束 Debug.Log("Slider拖动结束"); } @@ -217,11 +251,16 @@ public class TouchClient : MonoBehaviour Slider slider = GetCurrentPageSlider(); if (slider != null) { + // 临时禁用OnValueChanged以防止初始化触发 + var onValueChanged = slider.onValueChanged; + slider.onValueChanged = new Slider.SliderEvent(); slider.value = 0f; // 重置Slider到0 slider.interactable = true; // 确保可交互 - // 绑定OnValueChanged事件 + // 恢复OnValueChanged并绑定 + slider.onValueChanged = onValueChanged; slider.onValueChanged.RemoveAllListeners(); slider.onValueChanged.AddListener((value) => OnSliderChanged(slider)); + lastSentProgress = 0f; // 重置最后发送的进度 Debug.Log($"初始化Slider: {pageName}, 值: {slider.value}"); } @@ -233,7 +272,7 @@ public class TouchClient : MonoBehaviour { if (isDraggingSlider) return; // 拖动时忽略服务器进度 - float progress = 0f; + float progress = -1f; lock (queueLock) { if (progressQueue.Count > 0) @@ -247,8 +286,17 @@ public class TouchClient : MonoBehaviour Slider slider = GetCurrentPageSlider(); if (slider != null) { - slider.value = progress * 100f; // 更新Slider值(0-100) - Debug.Log($"更新Slider进度: {progress:F2}, Slider值: {slider.value}"); + // 仅当进度与当前Slider值差异较大或接近1.0时更新 + float currentProgress = slider.value / 100f; + if (progress > 0f || Mathf.Abs(progress - 1f) < 0.005f) + { + // 临时禁用OnValueChanged以防止循环触发 + var onValueChanged = slider.onValueChanged; + slider.onValueChanged = new Slider.SliderEvent(); + slider.value = progress * 100f; // 更新Slider值(0-100) + slider.onValueChanged = onValueChanged; // 恢复事件 + Debug.Log($"更新Slider进度: {progress:F2}, Slider值: {slider.value}"); + } } } } diff --git a/UserSettings/EditorUserSettings.asset b/UserSettings/EditorUserSettings.asset index 4cf705a..77851ed 100644 --- a/UserSettings/EditorUserSettings.asset +++ b/UserSettings/EditorUserSettings.asset @@ -12,10 +12,10 @@ EditorUserSettings: value: 54035756510d5a0c095f0d7414760b4446154b782e7b7063752a1b62e7b5363b flags: 0 RecentlyUsedSceneGuid-2: - value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a + value: 5303510050530a0a0e58087140210b44474f1a78742973637a2a4560b5b3656d flags: 0 RecentlyUsedSceneGuid-3: - value: 5303510050530a0a0e58087140210b44474f1a78742973637a2a4560b5b3656d + value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a flags: 0 vcSharedLogLevel: value: 0d5e400f0650 diff --git a/UserSettings/Layouts/default-2021.dwlt b/UserSettings/Layouts/default-2021.dwlt index 5307226..da5d618 100644 --- a/UserSettings/Layouts/default-2021.dwlt +++ b/UserSettings/Layouts/default-2021.dwlt @@ -99,7 +99,7 @@ MonoBehaviour: m_MinSize: {x: 300, y: 200} m_MaxSize: {x: 24288, y: 16192} vertical: 0 - controlID: 58 + controlID: 70 --- !u!114 &5 MonoBehaviour: m_ObjectHideFlags: 52 @@ -174,7 +174,7 @@ MonoBehaviour: m_MinSize: {x: 100, y: 200} m_MaxSize: {x: 8096, y: 16192} vertical: 1 - controlID: 31 + controlID: 38 --- !u!114 &8 MonoBehaviour: m_ObjectHideFlags: 52 @@ -194,8 +194,8 @@ MonoBehaviour: y: 0 width: 403.19995 height: 722.8 - m_MinSize: {x: 276, y: 71} - m_MaxSize: {x: 4001, y: 4021} + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} m_ActualView: {fileID: 13} m_Panes: - {fileID: 13} @@ -219,7 +219,7 @@ MonoBehaviour: x: 0 y: 0 width: 242.40002 - height: 538.4 + height: 400.8 m_MinSize: {x: 202, y: 221} m_MaxSize: {x: 4002, y: 4021} m_ActualView: {fileID: 16} @@ -243,9 +243,9 @@ MonoBehaviour: m_Position: serializedVersion: 2 x: 0 - y: 538.4 + y: 400.8 width: 242.40002 - height: 184.39996 + height: 322 m_MinSize: {x: 232, y: 271} m_MaxSize: {x: 10002, y: 10021} m_ActualView: {fileID: 14} @@ -284,7 +284,7 @@ MonoBehaviour: m_OverlaysVisible: 1 m_LockTracker: m_IsLocked: 0 - m_LastSelectedObjectID: 1946270 + m_LastSelectedObjectID: 656666 --- !u!114 &12 MonoBehaviour: m_ObjectHideFlags: 52 @@ -481,9 +481,9 @@ MonoBehaviour: m_Pos: serializedVersion: 2 x: 890.4 - y: 612 + y: 474.4 width: 240.40002 - height: 163.39996 + height: 301 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -515,7 +515,7 @@ MonoBehaviour: scrollPos: {x: 0, y: 0} m_SelectedIDs: 7c780000 m_LastClickedID: 30844 - m_ExpandedIDs: 0000000024ac010026ac010028ac01002aac01002cac01002eac010030ac0100 + m_ExpandedIDs: 00000000745d0000765d0000785d00007a5d00007c5d00007e5d0000805d0000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -540,10 +540,10 @@ MonoBehaviour: m_Icon: {fileID: 0} m_ResourceFile: m_AssetTreeState: - scrollPos: {x: 0, y: 300} + scrollPos: {x: 0, y: 0} m_SelectedIDs: m_LastClickedID: 0 - m_ExpandedIDs: ffffffff0000000024ac010026ac010028ac01002aac01002cac01002eac010030ac0100 + m_ExpandedIDs: ffffffff00000000745d0000765d0000785d00007a5d00007c5d00007e5d0000805d0000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -869,9 +869,9 @@ MonoBehaviour: m_PlayAudio: 0 m_AudioPlay: 0 m_Position: - m_Target: {x: 1664, y: 676, z: 0} + m_Target: {x: 1470.8665, y: 599.2432, z: -36.813965} speed: 2 - m_Value: {x: 1663.9999, y: 675.99994, z: 0.0000059604645} + m_Value: {x: 1470.8665, y: 599.2432, z: -36.813965} m_RenderMode: 0 m_CameraMode: drawMode: 0 @@ -918,13 +918,13 @@ MonoBehaviour: m_GridAxis: 1 m_gridOpacity: 0.5 m_Rotation: - m_Target: {x: 0.0725394, y: -0.011645896, z: 0.00085166015, w: 0.99730253} + m_Target: {x: 0.015004154, y: 0.020719247, z: -0.00030632256, w: 0.9996792} speed: 2 - m_Value: {x: -0.072539404, y: 0.011645896, z: -0.00085166015, w: -0.99730253} + m_Value: {x: 0.015004057, y: 0.020719113, z: -0.00030632058, w: 0.9996728} m_Size: - m_Target: 1564.3491 + m_Target: 987.1142 speed: 2 - m_Value: 1638.0619 + m_Value: 987.1142 m_Ortho: m_Target: 0 speed: 2 @@ -972,7 +972,7 @@ MonoBehaviour: x: 890.4 y: 73.6 width: 240.40002 - height: 517.4 + height: 379.8 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -981,9 +981,9 @@ MonoBehaviour: m_SceneHierarchy: m_TreeViewState: scrollPos: {x: 0, y: 0} - m_SelectedIDs: 9eb00100 - m_LastClickedID: 110750 - m_ExpandedIDs: 8e3affff08fbffff + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: 9255feffe255feff2857feff7c5afeffcc5afeff165cfeff021ffffff420ffff4821ffff8a22ffff5624ffffc427ffff1428ffff5a29ffffa42cfffff42cffff3a2effffb031ffff0432ffff4e33ffff86f6ffffc2f7ffff12f8ffff54f9ffff08fbffff1271030070c9030022f60700804e080046040a001a070a00ae070a00b6070a00f8070a00 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -1071,7 +1071,7 @@ MonoBehaviour: m_HSlider: 0 m_VSlider: 0 m_IgnoreScrollWheelUntilClicked: 0 - m_EnableMouseInput: 1 + m_EnableMouseInput: 0 m_EnableSliderZoomHorizontal: 0 m_EnableSliderZoomVertical: 0 m_UniformScale: 1