122 lines
6.1 KiB
C#
122 lines
6.1 KiB
C#
using UnityEngine;
|
||
|
||
namespace UI
|
||
{
|
||
/// <summary>
|
||
/// 技能节点连接线UI组件。
|
||
/// 该组件用于管理贝塞尔曲线的生成和显示,连接两个技能节点或其他UI元素。
|
||
/// 它通过控制贝塞尔曲线生成器的参数,实现UI元素之间的视觉连接。
|
||
/// </summary>
|
||
// 确保当前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;
|
||
|
||
/// <summary>
|
||
/// 当脚本实例被启用时,或者首次加载时调用。
|
||
/// 用于初始化和检查必要的组件。
|
||
/// </summary>
|
||
private void Awake()
|
||
{
|
||
// 获取当前GameObject的RectTransform组件。
|
||
rectTransform = GetComponent<RectTransform>();
|
||
|
||
// 检查贝塞尔曲线生成器是否已赋值。
|
||
if (curveGenerator == null)
|
||
{
|
||
Debug.LogError("UIBezierCurveGenerator未赋值给SkillNodeLinkLineUI!", this);
|
||
}
|
||
// 检查UILineRenderer是否已赋值。
|
||
// 注意:UILineRenderer通常由UIBezierCurveGenerator管理,但此处也进行一个警告检查。
|
||
if (line == null)
|
||
{
|
||
Debug.LogWarning("UILineRenderer未赋值给SkillNodeLinkLineUI。它可能由UIBezierCurveGenerator自动处理,或需要手动赋值。", this);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置曲线的起始点和结束点,并更新贝塞尔曲线的生成以及线头线尾UI元素的位置。
|
||
/// </summary>
|
||
/// <param name="startWorldPos">曲线起始点的世界坐标。</param>
|
||
/// <param name="endWorldPos">曲线结束点的世界坐标。</param>
|
||
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<RectTransform>();
|
||
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元素移动到结束点的世界坐标。
|
||
}
|
||
}
|
||
}
|
||
}
|