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; // 整体结束点相对于参照点的向上偏移量 /// /// 初始化连接线。根据传入的起始点数组创建多条连接线, /// 这些线的结束点将围绕 transform.position - new Vector3(6,0) 并在其基础上向上偏移5, /// 纵向均匀排列,至少间距12。 /// 在每次调用前,会清空所有旧的连接线以避免累积。 /// /// 要连接的线起始点数组。 /// 所有连接线的结束点所占据的最小总高度。 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() != null) { Destroy(child.gameObject); } } // 预制体加载检查:确保在执行任何操作之前,预制体已经加载。 // 优先使用Inspector赋值,如果 skillNodeLinkLineUIPrefab 为 null,则尝试从 Resources 文件夹加载作为备用方案。 if (skillNodeLinkLineUIPrefab == null) { // 从Resources加载预制体。 skillNodeLinkLineUIPrefab = Resources.Load("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; } } }