112 lines
5.9 KiB
C#
112 lines
5.9 KiB
C#
using UnityEngine;
|
||
|
||
namespace UI
|
||
{
|
||
public class SkillNodeEnterLineUI : MonoBehaviour
|
||
{
|
||
[SerializeField] private SkillNodeLinkLineUI skillNodeLinkLineUIPrefab;
|
||
|
||
private const float MIN_VERTICAL_SPACING = 12.9447f; // 每条连接线的最小垂直间距
|
||
private const float UPWARD_OFFSET_FROM_BASE = 0f; // 整体结束点相对于参照点的向上偏移量
|
||
|
||
/// <summary>
|
||
/// 初始化连接线。根据传入的起始点数组创建多条连接线,
|
||
/// 这些线的结束点将围绕 transform.position - new Vector3(6,0) 并在其基础上向上偏移5,
|
||
/// 纵向均匀排列,至少间距12。
|
||
/// 在每次调用前,会清空所有旧的连接线以避免累积。
|
||
/// </summary>
|
||
/// <param name="startPoints">要连接的线起始点数组。</param>
|
||
/// <returns>所有连接线的结束点所占据的最小总高度。</returns>
|
||
public float Init(Vector2[] startPoints)
|
||
{
|
||
// 清空所有旧的连接线,避免重复调用时线累积。
|
||
// 从后往前遍历子对象,因为销毁子对象会改变子对象列表的索引。
|
||
for (var i = transform.childCount - 1; i >= 0; i--)
|
||
{
|
||
// 获取当前子对象。
|
||
var child = transform.GetChild(i);
|
||
// 仅销毁SkillNodeLinkLineUI类型的子对象实例,避免意外删除其他非连接线的子对象。
|
||
if (child != null && child.GetComponent<SkillNodeLinkLineUI>() != null)
|
||
{
|
||
Destroy(child.gameObject);
|
||
}
|
||
}
|
||
|
||
// 预制体加载检查:确保在执行任何操作之前,预制体已经加载。
|
||
// 优先使用Inspector赋值,如果 skillNodeLinkLineUIPrefab 为 null,则尝试从 Resources 文件夹加载作为备用方案。
|
||
if (skillNodeLinkLineUIPrefab == null)
|
||
{
|
||
// 从Resources加载预制体。
|
||
skillNodeLinkLineUIPrefab = Resources.Load<SkillNodeLinkLineUI>("Prefab/SkillTree/linkLine");
|
||
if (skillNodeLinkLineUIPrefab == null)
|
||
{
|
||
// 打印错误日志(已本地化为中文)。
|
||
Debug.LogError(
|
||
"初始化失败:SkillNodeLinkLineUI 预制体未在 Prefab/SkillTree/linkLine 路径找到。请检查路径,确保预制体存在,或直接在 Inspector 中赋值。");
|
||
return 0f; // 预制体缺失,返回0高度。
|
||
}
|
||
}
|
||
|
||
// 获取起始点的数量。
|
||
var numLines = startPoints.Length;
|
||
if (numLines == 0)
|
||
{
|
||
// 没有起始点,不需要绘制连接线,返回0高度。
|
||
// 此时,清理旧连接线的逻辑已经执行,确保了没有残留的线。
|
||
return 0f;
|
||
}
|
||
|
||
// 计算所有连接线共享的基准结束点X坐标。
|
||
// 这是所有连接线结束点集合的垂直居中轴线。
|
||
var commonEndPointX = transform.position.x - 6f;
|
||
// 计算所有连接线结束点集合的实际垂直中心Y坐标。
|
||
// 根据需求 "有多个点时向上偏移5",这个偏移量应用于整个结束点集合的中心。
|
||
var effectiveCenterY = transform.position.y + UPWARD_OFFSET_FROM_BASE;
|
||
// 初始化所有线结束点所占据的总垂直跨度。
|
||
var requiredHeight = 0f;
|
||
|
||
if (numLines == 1)
|
||
{
|
||
// 只有一个起始点时,其结束点直接放在计算出的有效中心Y坐标上。
|
||
var endPoint = new Vector2(commonEndPointX, effectiveCenterY);
|
||
|
||
// 实例化连接线预制体并设置为当前对象的子对象。
|
||
var line = Instantiate(skillNodeLinkLineUIPrefab, transform);
|
||
// 设置连接线的起始点和结束点。
|
||
line.SetConnectionPoints(startPoints[0], endPoint);
|
||
|
||
// 只有一个点时,垂直高度可以认为是0,因为它不形成一个跨越多个点的“总高度”。
|
||
// 这里返回0f符合“所有连接线的结束点所占据的最小总高度”的定义语义。
|
||
requiredHeight = 0f;
|
||
}
|
||
else // numLines > 1
|
||
{
|
||
// 计算所有连接线结束点所占据的总垂直跨度(从最顶端到最底端)。
|
||
// 这是从最上面一条线的结束点Y到最下面一条线的结束点Y的距离。
|
||
requiredHeight = (numLines - 1) * MIN_VERTICAL_SPACING;
|
||
// 计算最上面一条线的结束点Y坐标。
|
||
// effectiveCenterY 是所有线的垂直中心,从这个中心向上偏移 requiredHeight / 2 即可得到最顶端的Y。
|
||
var currentEndPointY = effectiveCenterY + (requiredHeight / 2f);
|
||
|
||
// 遍历起始点数组,创建并设置每条连接线。
|
||
for (var i = 0; i < numLines; i++)
|
||
{
|
||
// 为当前连接线确定结束点坐标。
|
||
var endPoint = new Vector2(commonEndPointX, currentEndPointY);
|
||
|
||
// 实例化连接线预制体。
|
||
var line = Instantiate(skillNodeLinkLineUIPrefab, transform);
|
||
// 设置连接线的起始点和结束点。
|
||
line.SetConnectionPoints(startPoints[i], endPoint);
|
||
|
||
// 为下一条线计算其结束点Y坐标(向下移动一个最小间距)。
|
||
currentEndPointY -= MIN_VERTICAL_SPACING;
|
||
}
|
||
}
|
||
|
||
// 返回所有连接线的结束点所占据的最小总高度。
|
||
return requiredHeight;
|
||
}
|
||
}
|
||
}
|