using UnityEngine; namespace EventBossFight { /// /// UI RectTransform 跟随另一 RectTransform(视频 Boss 挂点,替代 Spine BoneFollower)。 /// 同一 rootCanvas 下直接同步世界坐标;否则经屏幕坐标转换到父 Rect 的局部空间。 /// [RequireComponent(typeof(RectTransform))] [DefaultExecutionOrder(1000)] public class EventBossFightRectFollowerGraphic : MonoBehaviour { [SerializeField] private RectTransform target; public RectTransform Target => target; public void SetTarget(RectTransform t) { target = t; } private void OnEnable() { ApplyFollow(); } private void LateUpdate() { ApplyFollow(); } private void ApplyFollow() { if (!target) return; var self = (RectTransform)transform; var parent = self.parent as RectTransform; if (!parent) { self.SetPositionAndRotation(target.position, target.rotation); return; } var canvasSelf = self.GetComponentInParent(); var canvasTarget = target.GetComponentInParent(); if (canvasSelf && canvasTarget && canvasSelf.rootCanvas == canvasTarget.rootCanvas) { self.SetPositionAndRotation(target.position, target.rotation); return; } var camTarget = GetEventCamera(canvasTarget); var camSelf = GetEventCamera(canvasSelf); // Overlay 下 WorldToScreenPoint 须传 null;Camera 模式用对应 Canvas 的 worldCamera Camera camForScreen = null; if (canvasTarget != null && canvasTarget.renderMode == RenderMode.ScreenSpaceOverlay) camForScreen = null; else camForScreen = camTarget ?? camSelf ?? Camera.main; var screenPoint = RectTransformUtility.WorldToScreenPoint(camForScreen, target.position); var camForParent = canvasSelf && canvasSelf.renderMode == RenderMode.ScreenSpaceOverlay ? null : camSelf ?? camForScreen; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, screenPoint, camForParent, out var localPoint)) { self.anchoredPosition = localPoint; self.localRotation = Quaternion.Inverse(parent.rotation) * target.rotation; } else self.SetPositionAndRotation(target.position, target.rotation); } private static Camera GetEventCamera(Canvas canvas) { if (!canvas || canvas.renderMode == RenderMode.ScreenSpaceOverlay) return null; return canvas.worldCamera; } } }