85 lines
2.9 KiB
C#
85 lines
2.9 KiB
C#
using UnityEngine;
|
||
|
||
namespace EventBossFight
|
||
{
|
||
/// <summary>
|
||
/// UI RectTransform 跟随另一 RectTransform(视频 Boss 挂点,替代 Spine BoneFollower)。
|
||
/// 同一 rootCanvas 下直接同步世界坐标;否则经屏幕坐标转换到父 Rect 的局部空间。
|
||
/// </summary>
|
||
[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<Canvas>();
|
||
var canvasTarget = target.GetComponentInParent<Canvas>();
|
||
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;
|
||
}
|
||
}
|
||
}
|