(client) feat:技能树节点及其素材

This commit is contained in:
m0_75251201
2025-09-11 11:19:34 +08:00
parent d1c0387df0
commit bb691f9622
79 changed files with 7904 additions and 364 deletions

View File

@ -0,0 +1,121 @@
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元素移动到结束点的世界坐标。
}
}
}
}