Files
Gen_Hack-and-Slash-Roguelit…/Client/Assets/Scripts/UI/SkillNodeLinkLineUI.cs
2025-09-11 11:19:34 +08:00

122 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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元素移动到结束点的世界坐标。
}
}
}
}