using UnityEngine; namespace UI { /// /// 技能节点连接线UI组件。 /// 该组件用于管理贝塞尔曲线的生成和显示,连接两个技能节点或其他UI元素。 /// 它通过控制贝塞尔曲线生成器的参数,实现UI元素之间的视觉连接。 /// // 确保当前GameObject拥有RectTransform组件,因为这是一个UI组件,其布局和定位依赖于它。 [RequireComponent(typeof(RectTransform))] public class SkillNodeLinkLineUI : MonoBehaviour { // 引用UILineRenderer组件,用于实际绘制曲线。 public UILineRenderer line; // 引用UIBezierCurveGenerator组件,负责根据控制点计算贝塞尔曲线的几何点。 public UIBezierCurveGenerator curveGenerator; // 曲线起始点关联的UI元素,例如:箭头的头部或起始连接点标识。 public GameObject lineHead; // 曲线结束点关联的UI元素,例如:箭头的尾部或结束连接点标识。 public GameObject lineTail; // 当前GameObject的RectTransform组件,方便在代码中直接访问和操作。 // [HideInInspector] 确保该字段在Inspector面板中不可见,通常因为它会被自动赋值。 [HideInInspector] public RectTransform rectTransform; /// /// 当脚本实例被启用时,或者首次加载时调用。 /// 用于初始化和检查必要的组件。 /// private void Awake() { // 获取当前GameObject的RectTransform组件。 rectTransform = GetComponent(); // 检查贝塞尔曲线生成器是否已赋值。 if (curveGenerator == null) { Debug.LogError("UIBezierCurveGenerator未赋值给SkillNodeLinkLineUI!", this); } // 检查UILineRenderer是否已赋值。 // 注意:UILineRenderer通常由UIBezierCurveGenerator管理,但此处也进行一个警告检查。 if (line == null) { Debug.LogWarning("UILineRenderer未赋值给SkillNodeLinkLineUI。它可能由UIBezierCurveGenerator自动处理,或需要手动赋值。", this); } } /// /// 设置曲线的起始点和结束点,并更新贝塞尔曲线的生成以及线头线尾UI元素的位置。 /// /// 曲线起始点的世界坐标。 /// 曲线结束点的世界坐标。 public void SetConnectionPoints(Vector2 startWorldPos, Vector2 endWorldPos) { // 如果贝塞尔曲线生成器未赋值,则无法设置连接点。 if (curveGenerator == null) { Debug.LogError("无法设置连接点:UIBezierCurveGenerator未赋值。", this); return; } // 1. 将世界坐标转换为 UIBezierCurveGenerator 的局部坐标。 // 贝塞尔曲线生成器的控制点是相对于其自身RectTransform的局部坐标。 // 因此,我们需要先获取curveGenerator所在GameObject的RectTransform,并进行坐标转换。 var curveGeneratorRectTransform = curveGenerator.GetComponent(); if (curveGeneratorRectTransform == null) { Debug.LogError("UIBezierCurveGenerator所在的GameObject没有RectTransform组件。", this); return; } // 将世界坐标转换为curveGeneratorRectTransform的局部坐标。 Vector2 localStartPos = curveGeneratorRectTransform.InverseTransformPoint(startWorldPos); Vector2 localEndPos = curveGeneratorRectTransform.InverseTransformPoint(endWorldPos); // 2. 计算贝塞尔曲线的水平偏移量,用于控制曲线的弯曲程度。 var horizontalOffset = 100f; // 默认水平偏移量。 // 根据起始点和结束点X坐标的绝对差值来调整偏移量,使曲线在近距离时更平滑。 var xDiff = Mathf.Abs(startWorldPos.x - endWorldPos.x); // 使用世界坐标计算X轴差值更直观。 if (xDiff < 200f) { horizontalOffset = xDiff / 2f + 10f; // 在X轴差值较小时,减小偏移量。 } // 3. 计算贝塞尔曲线的四个控制点 (P0, P1, P2, P3)。 var p0 = localStartPos; // 贝塞尔曲线的起始点。 var p3 = localEndPos; // 贝塞尔曲线的终止点。 Vector2 p1, p2; // 贝塞尔曲线的两个控制点。 // 根据起始点和结束点X坐标的相对位置,确定控制点P1和P2的水平偏移方向، // 以保证曲线的自然走向。 if (localStartPos.x <= localEndPos.x) { // 如果曲线从左向右(或垂直),P1在P0右侧,P2在P3左侧。 p1 = new Vector2(localStartPos.x + horizontalOffset, localStartPos.y); p2 = new Vector2(localEndPos.x - horizontalOffset, localEndPos.y); } else { // 如果曲线从右向左,P1在P0左侧,P2在P3右侧。 p1 = new Vector2(localStartPos.x - horizontalOffset, localStartPos.y); p2 = new Vector2(localEndPos.x + horizontalOffset, localEndPos.y); } // 4. 将计算出的控制点设置给 UIBezierCurveGenerator,使其生成新的曲线。 curveGenerator.SetControlPoints(p0, p1, p2, p3); // 5. 将线头和线尾UI元素移动到对应的世界坐标位置,使其与曲线的起始和结束对齐。 if (lineHead != null) { lineHead.transform.position = startWorldPos; // 将线头UI元素移动到起始点的世界坐标。 } if (lineTail != null) { lineTail.transform.position = endWorldPos; // 将线尾UI元素移动到结束点的世界坐标。 } } } }