using UnityEngine; public class WebViewPanelFollower : MonoBehaviour { public RectTransform panelRect; // 拖拽要跟随的 UI Panel 的 RectTransform public Camera uiCamera; // UI 相机,通常是 Canvas 的 Event Camera private Rect lastPanelRect; private WebViewWin32.RECT lastUnityWindowRect; private bool hasLastRect = false; // track subscription private bool subscribedToWebViewReady = false; void OnEnable() { TrySubscribeWebViewReady(); } void OnDisable() { if (subscribedToWebViewReady && WebViewLauncher.Instance != null) { WebViewLauncher.Instance.WebViewReady -= OnWebViewReady; subscribedToWebViewReady = false; } } void TrySubscribeWebViewReady() { if (!subscribedToWebViewReady && WebViewLauncher.Instance != null) { WebViewLauncher.Instance.WebViewReady += OnWebViewReady; subscribedToWebViewReady = true; } } void Update() { // Ensure subscription in case WebViewLauncher wasn't ready earlier TrySubscribeWebViewReady(); if (panelRect == null || uiCamera == null || WebViewLauncher.Instance == null) return; // 获取当前 panel 的屏幕矩形 Rect currentPanelRect = GetPanelScreenRect(panelRect); // 获取当前 Unity 窗口位置(仅在 build 中需要) WebViewWin32.RECT currentUnityWindowRect = new WebViewWin32.RECT(); #if !UNITY_EDITOR if (!WebViewWin32.TryGetClientScreenRect(System.Diagnostics.Process.GetCurrentProcess(), out currentUnityWindowRect)) return; #endif // 检查是否需要更新 if (!hasLastRect || !ApproximatelyEqual(currentPanelRect, lastPanelRect) #if !UNITY_EDITOR || !WindowRectsEqual(currentUnityWindowRect, lastUnityWindowRect) #endif ) { int x, y; #if UNITY_EDITOR // 在编辑器中,直接使用屏幕坐标(相对于屏幕左上角) x = Mathf.RoundToInt(currentPanelRect.x); y = Mathf.RoundToInt(Screen.height - currentPanelRect.y - currentPanelRect.height); #else // 在 build 中,使用 Unity 窗口位置 + 相对坐标 x = Mathf.RoundToInt(currentUnityWindowRect.Left + currentPanelRect.x); y = Mathf.RoundToInt(currentUnityWindowRect.Top + (Screen.height - currentPanelRect.y - currentPanelRect.height)); #endif int w = Mathf.RoundToInt(currentPanelRect.width); int h = Mathf.RoundToInt(currentPanelRect.height); // 更新 WebView 窗口 bool success = WebViewLauncher.Instance.TryUpdateWebViewRect(x, y, w, h); if (success) { lastPanelRect = currentPanelRect; #if !UNITY_EDITOR lastUnityWindowRect = currentUnityWindowRect; #endif hasLastRect = true; } } } void OnWebViewReady() { // Force next update to recalc and send position, and also perform immediate update hasLastRect = false; UpdatePositionNow(); } // perform immediate position update (same logic as in Update) void UpdatePositionNow() { if (panelRect == null || uiCamera == null || WebViewLauncher.Instance == null) return; Rect currentPanelRect = GetPanelScreenRect(panelRect); WebViewWin32.RECT currentUnityWindowRect = new WebViewWin32.RECT(); #if !UNITY_EDITOR if (!WebViewWin32.TryGetClientScreenRect(System.Diagnostics.Process.GetCurrentProcess(), out currentUnityWindowRect)) return; #endif int x, y; #if UNITY_EDITOR x = Mathf.RoundToInt(currentPanelRect.x); y = Mathf.RoundToInt(Screen.height - currentPanelRect.y - currentPanelRect.height); #else x = Mathf.RoundToInt(currentUnityWindowRect.Left + currentPanelRect.x); y = Mathf.RoundToInt(currentUnityWindowRect.Top + (Screen.height - currentPanelRect.y - currentPanelRect.height)); #endif int w = Mathf.RoundToInt(currentPanelRect.width); int h = Mathf.RoundToInt(currentPanelRect.height); bool success = WebViewLauncher.Instance.TryUpdateWebViewRect(x, y, w, h); if (success) { lastPanelRect = currentPanelRect; #if !UNITY_EDITOR lastUnityWindowRect = currentUnityWindowRect; #endif hasLastRect = true; } } Rect GetPanelScreenRect(RectTransform rect) { Vector3[] corners = new Vector3[4]; rect.GetWorldCorners(corners); Vector2 min = RectTransformUtility.WorldToScreenPoint(uiCamera, corners[0]); Vector2 max = RectTransformUtility.WorldToScreenPoint(uiCamera, corners[2]); return new Rect(min.x, min.y, max.x - min.x, max.y - min.y); } bool ApproximatelyEqual(Rect a, Rect b) { return Mathf.Approximately(a.x, b.x) && Mathf.Approximately(a.y, b.y) && Mathf.Approximately(a.width, b.width) && Mathf.Approximately(a.height, b.height); } bool WindowRectsEqual(WebViewWin32.RECT a, WebViewWin32.RECT b) { return a.Left == b.Left && a.Top == b.Top && a.Right == b.Right && a.Bottom == b.Bottom; } }