(client) feat:技能树节点及其素材
This commit is contained in:
@ -2,147 +2,174 @@ using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
// 需要引用 UILineRenderer 组件
|
||||
/// <summary>
|
||||
/// UI贝塞尔曲线生成器。
|
||||
/// 此组件用于生成和显示三次贝塞尔曲线,并将其点数据传递给UILineRenderer进行绘制。
|
||||
/// </summary>
|
||||
// 确保当前GameObject上存在UILineRenderer组件,如果不存在则会自动添加。
|
||||
[RequireComponent(typeof(UILineRenderer))]
|
||||
// 允许在编辑器模式下实时更新,便于调试
|
||||
// 允许在编辑器模式下,当参数修改时实时更新曲线,便于调试和预览。
|
||||
[ExecuteAlways]
|
||||
public class UIBezierCurveGenerator : MonoBehaviour
|
||||
{
|
||||
// UILineRenderer 组件的引用
|
||||
// 对UILineRenderer组件的引用,用于绘制生成的贝塞尔曲线。
|
||||
[SerializeField] public UILineRenderer lineRenderer;
|
||||
|
||||
// 控制点
|
||||
[Header("Bezier Control Points")] public Vector2 P0; // 起点
|
||||
public Vector2 P1; // 第一个控制点
|
||||
public Vector2 P2; // 第二个控制点
|
||||
public Vector2 P3; // 终点
|
||||
// 贝塞尔曲线的四个控制点。
|
||||
[Header("贝塞尔控制点")]
|
||||
public Vector2 P0; // 曲线的起始点。
|
||||
public Vector2 P1; // 曲线的第一个控制点,影响曲线从P0开始的方向和曲率。
|
||||
public Vector2 P2; // 曲线的第二个控制点,影响曲线在接近P3时的方向和曲率。
|
||||
public Vector2 P3; // 曲线的终止点。
|
||||
|
||||
[Header("Curve Settings")] [Range(5, 200)] // 限制段数范围,防止过低导致不平滑,过高导致性能问题
|
||||
public int segmentCount = 50; // 曲线的平滑度,即采样的线段数量
|
||||
// 曲线的设置参数。
|
||||
[Header("曲线设置")]
|
||||
[Range(5, 200)] // 限制曲线段数的范围,确保曲线平滑度和性能之间的平衡。
|
||||
public int segmentCount = 50; // 用于近似曲线的线段数量,值越大曲线越平滑。
|
||||
|
||||
/// <summary>
|
||||
/// 当脚本实例被启用时,或者首次加载时调用。
|
||||
/// </summary>
|
||||
void Awake()
|
||||
{
|
||||
// 初始化组件,获取UILineRenderer的引用。
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当在编辑器中修改脚本的属性时调用。
|
||||
/// </summary>
|
||||
void OnValidate()
|
||||
{
|
||||
// 初始化组件,获取UILineRenderer的引用。
|
||||
Initialize();
|
||||
// 如果UILineRenderer组件有效,则在编辑器中实时重新生成曲线。
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
GenerateCurvePoints(); // 在编辑器中修改参数时实时更新曲线
|
||||
GenerateCurvePoints();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化组件,获取 UILineRenderer 引用
|
||||
/// 初始化组件,获取 UILineRenderer 引用。
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
// 如果UILineRenderer引用为空,则尝试获取组件。
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
lineRenderer = GetComponent<UILineRenderer>();
|
||||
// 如果仍然无法获取UILineRenderer组件,则报错并禁用此组件。
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
Debug.LogError("UILineRenderer component not found on this GameObject. Please add one.", this);
|
||||
enabled = false; // 禁用此组件,防止空引用错误
|
||||
Debug.LogError("UILineRenderer组件未在此GameObject上找到,请添加一个。", this);
|
||||
enabled = false; // 禁用此组件实例,以防止后续空引用错误。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算三次贝塞尔曲线上的点
|
||||
/// B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P3
|
||||
/// 计算三次贝塞尔曲线上的特定点。
|
||||
/// 贝塞尔曲线公式: B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P3
|
||||
/// </summary>
|
||||
/// <param name="t">参数,范围 [0, 1]</param>
|
||||
/// <param name="p0">起点</param>
|
||||
/// <param name="p1">第一个控制点</param>
|
||||
/// <param name="p2">第二个控制点</param>
|
||||
/// <param name="p3">终点</param>
|
||||
/// <returns>在参数 t 处的贝塞尔曲线上点</returns>
|
||||
/// <param name="t">参数,表示曲线上的位置,范围 [0, 1]。</param>
|
||||
/// <param name="p0">曲线的起始点。</param>
|
||||
/// <param name="p1">曲线的第一个控制点。</param>
|
||||
/// <param name="p2">曲线的第二个控制点。</param>
|
||||
/// <param name="p3">曲线的终止点。</param>
|
||||
/// <returns>在参数 t 处的贝塞尔曲线上点的二维坐标。</returns>
|
||||
private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||
{
|
||||
float u = 1 - t;
|
||||
float tt = t * t;
|
||||
float uu = u * u;
|
||||
float uuu = uu * u;
|
||||
float ttt = tt * t;
|
||||
var u = 1 - t; // 计算 (1-t)
|
||||
var tt = t * t; // 计算 t的平方
|
||||
var uu = u * u; // 计算 (1-t)的平方
|
||||
var uuu = uu * u; // 计算 (1-t)的立方
|
||||
var ttt = tt * t; // 计算 t的立方
|
||||
|
||||
Vector2 p = uuu * p0; // (1-t)^3 * P0
|
||||
p += 3 * uu * t * p1; // 3 * (1-t)^2 * t * P1
|
||||
p += 3 * u * tt * p2; // 3 * (1-t) * t^2 * P2
|
||||
p += ttt * p3; // t^3 * P3
|
||||
var p = uuu * p0; // 计算 (1-t)^3 * P0
|
||||
p += 3 * uu * t * p1; // 计算 3 * (1-t)^2 * t * P1
|
||||
p += 3 * u * tt * p2; // 计算 3 * (1-t) * t^2 * P2
|
||||
p += ttt * p3; // 计算 t^3 * P3
|
||||
|
||||
return p;
|
||||
return p; // 返回计算出的贝塞尔曲线上点。
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成贝塞尔曲线的点并更新 UILineRenderer
|
||||
/// 根据当前的控制点和段数生成贝塞尔曲线上的所有点,并更新 UILineRenderer 进行绘制。
|
||||
/// </summary>
|
||||
public void GenerateCurvePoints()
|
||||
{
|
||||
if (lineRenderer == null || segmentCount <= 0)
|
||||
// 如果UILineRenderer组件无效,则无法生成曲线。
|
||||
if (!lineRenderer)
|
||||
{
|
||||
Debug.LogWarning("UILineRenderer is null or segmentCount is invalid. Cannot generate curve.", this);
|
||||
Debug.LogWarning("UILineRenderer组件为空,无法生成曲线。", this);
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空 UILineRenderer 的点列表,以便重新填充
|
||||
// 清空 UILineRenderer 当前的点列表,为填充新的曲线点做准备。
|
||||
lineRenderer.points.Clear();
|
||||
|
||||
for (int i = 0; i <= segmentCount; i++)
|
||||
// 遍历并计算曲线上的所有采样点。
|
||||
for (var i = 0; i <= segmentCount; i++)
|
||||
{
|
||||
float t = i / (float)segmentCount;
|
||||
Vector2 point = CalculateBezierPoint(t, P0, P1, P2, P3);
|
||||
lineRenderer.points.Add(point);
|
||||
var t = i / (float)segmentCount; // 计算当前点的归一化参数 [0, 1]。
|
||||
var point = CalculateBezierPoint(t, P0, P1, P2, P3); // 根据参数 t 计算贝塞尔曲线上点坐标。
|
||||
lineRenderer.points.Add(point); // 将计算出的点添加到UILineRenderer的点列表中。
|
||||
}
|
||||
|
||||
// 通知 UILineRenderer 需要重新绘制其几何体
|
||||
// 通知 UILineRenderer 需要重新绘制其几何体,以显示更新后的曲线。
|
||||
lineRenderer.SetAllDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供了通过代码设置控制点并刷新曲线的方法
|
||||
/// 提供了通过代码设置贝塞尔曲线控制点的方法,并立即刷新曲线。
|
||||
/// </summary>
|
||||
/// <param name="p0">新的起始点。</param>
|
||||
/// <param name="p1">新的第一个控制点。</param>
|
||||
/// <param name="p2">新的第二个控制点。</param>
|
||||
/// <param name="p3">新的终止点。</param>
|
||||
public void SetControlPoints(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||
{
|
||||
this.P0 = p0;
|
||||
this.P1 = p1;
|
||||
this.P2 = p2;
|
||||
this.P3 = p3;
|
||||
GenerateCurvePoints();
|
||||
this.P0 = p0; // 设置起始点。
|
||||
this.P1 = p1; // 设置第一个控制点。
|
||||
this.P2 = p2; // 设置第二个控制点。
|
||||
this.P3 = p3; // 设置终止点。
|
||||
GenerateCurvePoints(); // 更新曲线。
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供了通过代码设置曲线段数并刷新曲线的方法
|
||||
/// 提供了通过代码设置贝塞尔曲线段数的方法,并立即刷新曲线。
|
||||
/// </summary>
|
||||
/// <param name="count">新的曲线段数。</param>
|
||||
public void SetSegmentCount(int count)
|
||||
{
|
||||
segmentCount = Mathf.Max(5, count); // 至少保留5段,保证一定平滑度
|
||||
GenerateCurvePoints();
|
||||
segmentCount = Mathf.Max(5, count); // 设置曲线段数,确保至少为5段以保持一定平滑度。
|
||||
GenerateCurvePoints(); // 更新曲线。
|
||||
}
|
||||
|
||||
// 当组件首次添加或重置时调用
|
||||
void Reset()
|
||||
/// <summary>
|
||||
/// 当组件首次添加到GameObject或在编辑器中选择“Reset”时调用。
|
||||
/// 用于设置组件的默认值。
|
||||
/// </summary>
|
||||
private void Reset()
|
||||
{
|
||||
Initialize(); // 确保 lineRenderer 已初始化
|
||||
Initialize(); // 确保UILineRenderer引用已初始化。
|
||||
|
||||
// 根据 RectTransform 的大小设置默认点,确保在可见范围内
|
||||
RectTransform rt = GetComponent<RectTransform>();
|
||||
float halfWidth = rt.rect.width / 2f;
|
||||
float halfHeight = rt.rect.height / 2f;
|
||||
// 获取当前GameObject的RectTransform,以便根据其尺寸设置默认控制点。
|
||||
var rt = GetComponent<RectTransform>();
|
||||
var halfWidth = rt.rect.width / 2f; // 获取RectTransform宽度的一半。
|
||||
var halfHeight = rt.rect.height / 2f; // 获取RectTransform高度的一半。
|
||||
|
||||
// 设置一些默认的控制点,让曲线在UI区域内可见
|
||||
// 这些是相对于 RectTransform 的局部坐标
|
||||
P0 = new Vector2(-halfWidth * 0.8f, -halfHeight * 0.5f); // 左下
|
||||
P1 = new Vector2(-halfWidth * 0.4f, halfHeight * 0.8f); // 左上控制点
|
||||
P2 = new Vector2(halfWidth * 0.4f, halfHeight * 0.8f); // 右上控制点
|
||||
P3 = new Vector2(halfWidth * 0.8f, -halfHeight * 0.5f); // 右下
|
||||
// 设置一组默认的控制点,使得曲线在UI区域内可见且具有S形或拱形。
|
||||
// 这些点是相对于RectTransform的局部坐标。
|
||||
P0 = new Vector2(-halfWidth * 0.8f, -halfHeight * 0.5f); // 默认起始点,位于左下。
|
||||
P1 = new Vector2(-halfWidth * 0.4f, halfHeight * 0.8f); // 默认第一个控制点,位于左上。
|
||||
P2 = new Vector2(halfWidth * 0.4f, halfHeight * 0.8f); // 默认第二个控制点,位于右上。
|
||||
P3 = new Vector2(halfWidth * 0.8f, -halfHeight * 0.5f); // 默认终止点,位于右下。
|
||||
|
||||
segmentCount = 50;
|
||||
segmentCount = 50; // 设置默认的曲线段数。
|
||||
|
||||
GenerateCurvePoints(); // 立即生成曲线
|
||||
GenerateCurvePoints(); // 立即根据默认设置生成并显示曲线。
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user