using System; using System.Collections.Generic; using SLSFramework.General; using UI_Spline_Renderer; using Unity.Mathematics; using UnityEngine; using UnityEngine.Splines; using UnityEngine.UI; namespace Continentis.MainGame.UI { public class PointerArrow : MonoBehaviour { [Tooltip("箭头起点的Transform(例如:正在拖拽的卡牌)")] public RectTransform startPoint; [Tooltip("箭头线条")] public SplineContainer splineContainer; public UISplineRenderer arrowBody; [Tooltip("箭头头部的图片")] public Image endImage; [Header("曲线设置")] [Tooltip("曲线的弯曲程度,数值越大越弯曲")] public float curveOffset = 150f; [Tooltip("曲线的平滑度,点越多越平滑,性能开销也越大")] [Range(1, 100)] public int lineSegments = 50; private void Awake() { GetComponent().sortingLayerName = "UI"; } public void SetArrow(Vector3 start, Vector3 end) { startPoint.position = start; Camera uiCamera = CombatUIManager.Instance.uiCamera; Camera worldCamera = CombatUIManager.Instance.combatCamera; RectTransform pageTransform = CombatUIManager.Instance.arrowsPage.rectTransform; Vector2 uiStart = SpaceConverter.WorldPointToUILocalPoint(pageTransform, start, uiCamera, worldCamera); Vector2 uiEnd = SpaceConverter.WorldPointToUILocalPoint(pageTransform, end, uiCamera, worldCamera); bool isEndOnLeftSide = uiEnd.x < uiStart.x; // 控制点在起点和终点的中点,并根据朝向进行偏移,使曲线更自然 Vector2 midPoint = (uiStart + uiEnd) / 2f; Vector2 direction = (uiEnd - uiStart).normalized; Vector2 perpendicular = new Vector2(-direction.y, direction.x); // 计算垂直向量 Vector2 controlPoint = midPoint + perpendicular * (isEndOnLeftSide ? -curveOffset : curveOffset); controlPoint += new Vector2(0, Mathf.Abs(uiEnd.y - uiStart.y)); //增加一些垂直偏移 //controlPoint += new Vector2(0f, 500f); splineContainer.Spline.Clear(); // 2. 计算贝塞尔曲线上所有的点 List knots = new List(); for (int i = 0; i < lineSegments; i++) { float t = (float)i / (lineSegments - 1); // 二次贝塞尔曲线公式: B(t) = (1-t)² * P₀ + 2(1-t)t * P₁ + t² * P₂ float3 point = math.pow(1 - t, 2) * new float3(uiStart.x, uiStart.y, 0) + 2 * (1 - t) * t * new float3(controlPoint.x, controlPoint.y, 0) + math.pow(t, 2) * new float3(uiEnd.x, uiEnd.y, 0); knots.Add(new BezierKnot(point)); } splineContainer.Spline.Knots = knots; arrowBody.SetAllDirty(); // 通知UI系统重绘 } public void SetColor(Color color) { if (color == Color.clear) { endImage.material.SetFloat("_SineGlowFade", 0); arrowBody.material.SetFloat("_SineGlowFade", 0); endImage.material.SetColor("_SineGlowColor", Color.white); arrowBody.material.SetColor("_SineGlowColor", Color.white); } else { float emissionIntensity = 1.5f; endImage.material.SetFloat("_SineGlowFade", 1); arrowBody.material.SetFloat("_SineGlowFade", 1); endImage.material.SetColor("_SineGlowColor", color * Mathf.Pow(2, emissionIntensity)); arrowBody.material.SetColor("_SineGlowColor", color * Mathf.Pow(2, emissionIntensity)); } } } }