(client) feat:添加UI多线段绘制器,贝塞尔曲线绘制器及其编辑器, fix:单目标子弹在一帧内击中多个目标未被限制击中数量

This commit is contained in:
m0_75251201
2025-09-09 20:10:21 +08:00
parent 6cb4483d20
commit d1c0387df0
17 changed files with 1142 additions and 117 deletions

View File

@ -14,7 +14,7 @@ namespace Base
}
// 自定义梯度效果类继承自BaseMeshEffect
public class Gradient : BaseMeshEffect
public class ColorBar : BaseMeshEffect
{
[SerializeField] // 序列化字段可在Inspector中编辑
private Dir dir = Dir.Vertical; // 渐变方向,默认垂直

View File

@ -29,7 +29,7 @@ namespace Base
/// 用于显示加载进度的自定义进度条组件。
/// <para>请参阅类注释以了解其声明类型与预期API的差异。</para>
/// </summary>
public Gradient progressBar;
public ColorBar progressBar;
/// <summary>
/// 用于显示当前加载步骤描述的文本组件。

View File

@ -36,7 +36,7 @@ namespace Entity
private void OnTriggerEnter2D(Collider2D other)
{
var entity = other.GetComponent<Entity>();
if (!entity || entity == bulletSource || entity is Pickup) return;
if (IsDead||!entity || entity == bulletSource || entity is Pickup) return;
if (Managers.AffiliationManager.Instance.GetRelation(bulletSource.affiliation, entity.affiliation) != Relation.Friendly || Setting.Instance.CurrentSettings.friendlyFire)
{
entity.OnHit(this);

View File

@ -216,6 +216,7 @@ namespace Entity
return;
weaponItem=GameObjectCreate.SpriteAnimator(currentWeapon.Icon.ToArray(), weaponAnimator.transform);
weaponItem.SetFPS(currentWeapon.FPS);
weaponItem.gameObject.SetActive(true);
weaponAttackAnimation = GameObjectCreate.SpriteAnimator(currentWeapon.AttackAnimation.ToArray(),
weaponAnimator.transform);
@ -393,7 +394,7 @@ namespace Entity
private void StartAttack(WeaponResource weaponResource)
{
_attackTimer = weaponResource.AttackCooldown;
_attackDetectionTime = weaponResource.AttackDetectionTime;
_attackDetectionTime =Mathf.Max(0,weaponResource.AttackCooldown- weaponResource.AttackDetectionTime);
currentAttackWeapon = weaponResource;
if (weaponResource.AttackAnimationTime > 0)
@ -594,8 +595,13 @@ namespace Entity
{
var mousePos = MousePosition.GetWorldPosition();
attackDirection = new Vector3(mousePos.x,mousePos.y) - Position;
RotateTool.RotateTransformToDirection(weaponItem.transform, attackDirection);
}
if (Input.GetKeyDown(KeyCode.V))
{
weaponItem.gameObject.SetActive(!weaponItem.gameObject.activeSelf);
}
// 获取当前键盘输入状态2D 移动,只使用 X 和 Y 轴)
var inputDirection = Vector2.zero;

View File

@ -0,0 +1,7 @@
namespace Prefab
{
public class SkillTreeNodeProfab
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 78843bef7bb2445495588f60349626d9
timeCreated: 1757395333

View File

@ -0,0 +1,148 @@
using UnityEngine;
namespace UI
{
// 需要引用 UILineRenderer 组件
[RequireComponent(typeof(UILineRenderer))]
// 允许在编辑器模式下实时更新,便于调试
[ExecuteAlways]
public class UIBezierCurveGenerator : MonoBehaviour
{
// UILineRenderer 组件的引用
[SerializeField] public UILineRenderer lineRenderer;
// 控制点
[Header("Bezier Control Points")] public Vector2 P0; // 起点
public Vector2 P1; // 第一个控制点
public Vector2 P2; // 第二个控制点
public Vector2 P3; // 终点
[Header("Curve Settings")] [Range(5, 200)] // 限制段数范围,防止过低导致不平滑,过高导致性能问题
public int segmentCount = 50; // 曲线的平滑度,即采样的线段数量
void Awake()
{
Initialize();
}
void OnValidate()
{
Initialize();
if (lineRenderer != null)
{
GenerateCurvePoints(); // 在编辑器中修改参数时实时更新曲线
}
}
/// <summary>
/// 初始化组件,获取 UILineRenderer 引用
/// </summary>
private void Initialize()
{
if (lineRenderer == null)
{
lineRenderer = GetComponent<UILineRenderer>();
if (lineRenderer == null)
{
Debug.LogError("UILineRenderer component not found on this GameObject. Please add one.", 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
/// </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>
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;
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
return p;
}
/// <summary>
/// 生成贝塞尔曲线的点并更新 UILineRenderer
/// </summary>
public void GenerateCurvePoints()
{
if (lineRenderer == null || segmentCount <= 0)
{
Debug.LogWarning("UILineRenderer is null or segmentCount is invalid. Cannot generate curve.", this);
return;
}
// 清空 UILineRenderer 的点列表,以便重新填充
lineRenderer.points.Clear();
for (int i = 0; i <= segmentCount; i++)
{
float t = i / (float)segmentCount;
Vector2 point = CalculateBezierPoint(t, P0, P1, P2, P3);
lineRenderer.points.Add(point);
}
// 通知 UILineRenderer 需要重新绘制其几何体
lineRenderer.SetAllDirty();
}
/// <summary>
/// 提供了通过代码设置控制点并刷新曲线的方法
/// </summary>
public void SetControlPoints(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
{
this.P0 = p0;
this.P1 = p1;
this.P2 = p2;
this.P3 = p3;
GenerateCurvePoints();
}
/// <summary>
/// 提供了通过代码设置曲线段数并刷新曲线的方法
/// </summary>
public void SetSegmentCount(int count)
{
segmentCount = Mathf.Max(5, count); // 至少保留5段保证一定平滑度
GenerateCurvePoints();
}
// 当组件首次添加或重置时调用
void Reset()
{
Initialize(); // 确保 lineRenderer 已初始化
// 根据 RectTransform 的大小设置默认点,确保在可见范围内
RectTransform rt = GetComponent<RectTransform>();
float halfWidth = rt.rect.width / 2f;
float halfHeight = rt.rect.height / 2f;
// 设置一些默认的控制点让曲线在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); // 右下
segmentCount = 50;
GenerateCurvePoints(); // 立即生成曲线
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8623ad98baf0495b8c8634232e3cae2e
timeCreated: 1757418458

View File

@ -0,0 +1,439 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using static UI.UILineRenderer; // 允许LineCapType直接访问
// 确保在UI命名空间内
namespace UI
{
/// <summary>
/// UILineRenderer 是一个用于在UI中绘制自定义线条的Graphic组件。
/// 它支持设置线条宽度、渐变颜色以及不同类型的线头(方形或圆形)。
/// 同时支持线段之间的斜切连接,以确保转角平滑。
/// </summary>
[RequireComponent(typeof(CanvasRenderer))]
public class UILineRenderer : Graphic
{
/// <summary>
/// 存储构成线条的顶点列表。
/// </summary>
public List<Vector2> points = new List<Vector2>();
/// <summary>
/// 线的宽度。
/// </summary>
[SerializeField] private float lineWidth = 5f;
/// <summary>
/// 获取或设置线的宽度。
/// 设置新值时如果宽度发生改变将触发UI网格的重新绘制。
/// </summary>
public float LineWidth
{
get => lineWidth;
set
{
// 仅当值发生显著变化时才更新,以避免不必要的重绘。
// Mathf.Abs(lineWidth - value) > float.Epsilon 是一个更健壮的浮点数比较方式。
if (Mathf.Abs(lineWidth - value) > float.Epsilon)
{
lineWidth = value;
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
}
}
/// <summary>
/// 用于线条的渐变颜色。
/// </summary>
public Gradient lineGradient = new Gradient();
/// <summary>
/// 定义线条两端的线头类型。
/// </summary>
public enum LineCapType
{
/// <summary>
/// 无线头。
/// </summary>
None,
/// <summary>
/// 方形线头。
/// </summary>
Square,
/// <summary>
/// 圆形线头。
/// </summary>
Round
}
/// <summary>
/// 线的起始端线头类型。
/// </summary>
public LineCapType startCap = LineCapType.None;
/// <summary>
/// 线的结束端线头类型。
/// </summary>
public LineCapType endCap = LineCapType.None;
/// <summary>
/// 获取用于UI渲染的相机。
/// 如果Canvas的渲染模式是Screen Space - Overlay则返回null此时不需要相机。
/// </summary>
/// <returns>用于UI渲染的Camera实例或在Overlay模式下返回null。</returns>
private Camera GetCanvasRenderCamera()
{
Canvas _canvas = GetComponentInParent<Canvas>();
// 作为Graphic组件总会有一个Canvas作为父级。
if (_canvas == null) return null;
// 对于ScreenSpaceOverlay模式不需要相机来将屏幕点转换为世界点。
return _canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : _canvas.worldCamera;
}
/// <summary>
/// 在UI需要被重新绘制时调用用于生成网格顶点数据。
/// </summary>
/// <param name="vh">VertexHelper用于构建UI元素的网格。</param>
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
// 如果点列表为空或点的数量不足以构成线段,则不绘制任何东西。
if (points == null || points.Count < 2)
return;
// 如果渐变色对象未设置或颜色键为空,则默认创建一个纯白色渐变。
if (lineGradient == null || lineGradient.colorKeys.Length == 0)
{
lineGradient = new Gradient();
lineGradient.SetKeys(
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) }
);
}
List<float> segmentLengths = new List<float>();
float totalLength = 0f;
// 预计算线条总长度和每段长度,用于渐变色和线头定位
for (int i = 0; i < points.Count - 1; i++)
{
float len = Vector2.Distance(points[i], points[i + 1]);
segmentLengths.Add(len);
totalLength += len;
}
// 存储计算出的所有顶点,包括内外侧及颜色信息
List<UIVertex> vertices = new List<UIVertex>();
float currentRenderedLength = 0f;
float halfWidth = lineWidth / 2f;
const float miterLimit = 4f; // Miter limit to prevent excessively long miters
for (int i = 0; i < points.Count; i++)
{
Vector2 p = points[i];
Vector2 currentPerp = Vector2.zero; // 垂直于期望线段方向的偏移向量
// 计算当前点的渐变颜色
float normalizedDistance = (totalLength > 0 && points.Count > 1) ? (currentRenderedLength / totalLength) : 0f;
Color pointColor = lineGradient.Evaluate(normalizedDistance);
if (i == 0) // 第一个点 (起点)
{
// 使用第一段的法线方向
Vector2 segmentDir = (points[1] - p).normalized;
currentPerp = new Vector2(-segmentDir.y, segmentDir.x) * halfWidth;
}
else if (i == points.Count - 1) // 最后一个点 (终点)
{
// 使用最后一段的法线方向
Vector2 segmentDir = (p - points[points.Count - 2]).normalized;
currentPerp = new Vector2(-segmentDir.y, segmentDir.x) * halfWidth;
}
else // 中间点 (转角)
{
Vector2 prevDir = (p - points[i - 1]).normalized;
Vector2 nextDir = (points[i + 1] - p).normalized;
// 计算两条线段的平均法线 (角平分线方向)
Vector2 angleBisector = (prevDir + nextDir).normalized;
// 计算垂直于角平分线的向量
Vector2 bisectorPerp = new Vector2(-angleBisector.y, angleBisector.x);
// 确定 bisectorPerp 的方向,使其始终指向“外侧”
// 通过检查 prevDir 和 bisectorPerp 的点积来判断方向
// 如果点积为负,表示 prevDir 的“向左”方向perp与 bisectorPerp 方向相反,需要翻转
// (prevDir.x * bisectorPerp.y - prevDir.y * bisectorPerp.x) > 0 表示 bisectorPerp 在 prevDir 的左侧
// (prevDir.x * bisectorPerp.y - prevDir.y * bisectorPerp.x) < 0 表示 bisectorPerp 在 prevDir 的右侧
// 更直观的判断是看prevDir的右向量和bisectorPerp是否同向
Vector2 prevDirPerp = new Vector2(-prevDir.y, prevDir.x); // prevDir的左侧法线
if (Vector2.Dot(prevDirPerp, bisectorPerp) < 0) // 如果bisectorPerp不是指向prevDir左侧则翻转
{
bisectorPerp *= -1;
}
// 计算斜切的延伸长度
// 角度越尖锐cos(angle/2) 越小miterFactor 越大
float angleRad = Vector2.Angle(prevDir, nextDir) * Mathf.Deg2Rad;
float miterLengthFactor = halfWidth / Mathf.Max(0.001f, Mathf.Cos(angleRad / 2f)); // 防止除以0
// 应用miter limit避免极端尖锐角造成过长斜切
miterLengthFactor = Mathf.Min(miterLengthFactor, lineWidth * miterLimit);
currentPerp = bisectorPerp * miterLengthFactor;
}
// 添加内外侧顶点
// Outer point
vertices.Add(new UIVertex
{
position = p + currentPerp,
color = pointColor,
uv0 = new Vector2(0, normalizedDistance) // Simple UV mapping for gradient, 0 for outer
});
// Inner point
vertices.Add(new UIVertex
{
position = p - currentPerp,
color = pointColor,
uv0 = new Vector2(1, normalizedDistance) // Simple UV mapping for gradient, 1 for inner
});
// 更新已渲染长度,用于下一个点的渐变计算
if (i < segmentLengths.Count)
{
currentRenderedLength += segmentLengths[i];
}
}
// --- 绘制线段网格 ---
for (int i = 0; i < points.Count - 1; i++)
{
int prevOuter = i * 2; // 上一个点的外侧顶点索引
int prevInner = i * 2 + 1; // 上一个点的内侧顶点索引
int currentOuter = (i + 1) * 2; // 当前点的外侧顶点索引
int currentInner = (i + 1) * 2 + 1; // 当前点的内侧顶点索引
// 添加顶点到 VertexHelper
// 确保vh.AddVert的顺序与vertices列表中的顺序一致
if (i == 0) // 为第一个点添加顶点
{
vh.AddVert(vertices[prevOuter]);
vh.AddVert(vertices[prevInner]);
}
vh.AddVert(vertices[currentOuter]);
vh.AddVert(vertices[currentInner]);
// 连接当前点和上一个点的顶点,形成一个矩形(两个三角形)
vh.AddTriangle(prevOuter, currentOuter, currentInner);
vh.AddTriangle(prevOuter, currentInner, prevInner);
}
// --- 绘制线头 ---
if (points.Count >= 2)
{
// 起点线头
Vector2 firstSegmentDirection = (points[1] - points[0]).normalized;
DrawCap(vh, points[0], -firstSegmentDirection, startCap, lineGradient.Evaluate(0f));
// 终点线头
Vector2 lastSegmentDirection = (points[points.Count - 1] - points[points.Count - 2]).normalized;
DrawCap(vh, points[points.Count - 1], lastSegmentDirection, endCap, lineGradient.Evaluate(1f));
}
}
/// <summary>
/// 绘制指定类型的线头。
/// </summary>
/// <param name="vh">VertexHelper用于构建线头网格。</param>
/// <param name="center">线头的中心(即线条的端点)。</param>
/// <param name="direction">线头延伸的方向。</param>
/// <param name="capType">线头类型(无、方形或圆形)。</param>
/// <param name="capColor">线头的颜色。</param>
private void DrawCap(VertexHelper vh, Vector2 center, Vector2 direction, LineCapType capType, Color capColor)
{
if (capType == LineCapType.None) return;
// 计算线头垂直于方向的向量,用于确定线头的宽度。
var perpendicular = new Vector2(-direction.y, direction.x) * lineWidth / 2f;
// 记录当前VertexHelper中的顶点数量。
var currentVertCount = vh.currentVertCount;
UIVertex vertexTemplate = UIVertex.simpleVert;
vertexTemplate.color = capColor;
if (capType == LineCapType.Square)
{
// 绘制方形线头,通过在端点处添加一个与线段垂直的矩形。
Vector2 p0 = center - perpendicular; // 线段边缘点1
Vector2 p1 = center + perpendicular; // 线段边缘点2
Vector2 p2 = center + perpendicular + (direction * (lineWidth / 2f)); // 延伸点1
Vector2 p3 = center - perpendicular + (direction * (lineWidth / 2f)); // 延伸点2
// 添加方形线头的四个顶点。
// 注意:这里需要确保顶点的顺序正确,形成两个三角形
vertexTemplate.position = p0; vertexTemplate.uv0 = new Vector2(0f, 0f); vh.AddVert(vertexTemplate); // 0
vertexTemplate.position = p1; vertexTemplate.uv0 = new Vector2(1f, 0f); vh.AddVert(vertexTemplate); // 1
vertexTemplate.position = p2; vertexTemplate.uv0 = new Vector2(1f, 1f); vh.AddVert(vertexTemplate); // 2
vertexTemplate.position = p3; vertexTemplate.uv0 = new Vector2(0f, 1f); vh.AddVert(vertexTemplate); // 3
// 添加两个三角形组成方形线头。
vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
}
else if (capType == LineCapType.Round)
{
const int segments = 12; // 增加段数使圆形更平滑
float radius = lineWidth / 2f; // 半圆的半径等于线宽的一半。
// 添加扇形中心点。
vertexTemplate.position = center;
vertexTemplate.uv0 = new Vector2(0.5f, 0.5f); // 中心UV
vh.AddVert(vertexTemplate);
var centerVertIndex = currentVertCount;
currentVertCount++;
// 计算半圆弧的起始角度 (垂直向量的角度) 和每段的扫过角度。
float baseAngle = Mathf.Atan2(perpendicular.y, perpendicular.x);
float angleSweepStep = Mathf.PI / segments; // 180度 / 段数。
List<int> arcVerticesIndices = new List<int>();
// 遍历并添加半圆弧上的点。
for (int j = 0; j <= segments; j++)
{
float angle = baseAngle - (j * angleSweepStep); // 逆时针扫描。
Vector2 pointOnArc = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * radius;
vertexTemplate.position = center + pointOnArc;
// 计算相对中心的UV使纹理正确映射到圆形。
vertexTemplate.uv0 = new Vector2(0.5f + pointOnArc.x / (radius * 2), 0.5f + pointOnArc.y / (radius * 2));
vh.AddVert(vertexTemplate);
arcVerticesIndices.Add(currentVertCount);
currentVertCount++;
}
// 连接扇形中心和弧上的相邻点形成三角形,构成半圆形线头。
for (int j = 0; j < arcVerticesIndices.Count - 1; j++)
{
vh.AddTriangle(centerVertIndex, arcVerticesIndices[j], arcVerticesIndices[j + 1]);
}
}
}
/// <summary>
/// 将一个UI元素的世界坐标转换为此UILineRenderer的局部坐标并将其作为线条上的一个点添加。
/// </summary>
/// <param name="uiElement">要作为线条点的RectTransform UI元素。</param>
public void AppendUIElement(RectTransform uiElement)
{
Vector2 localPoint; // 转换后的局部坐标。
// 将UI元素的世界坐标转换为屏幕坐标再将屏幕坐标转换为当前UILineRenderer的局部坐标。
RectTransformUtility.ScreenPointToLocalPointInRectangle(
rectTransform, // 当前 UILineRenderer 的 RectTransform。
RectTransformUtility.WorldToScreenPoint(GetCanvasRenderCamera(), uiElement.position), // UI 元素的世界坐标转换为屏幕坐标。
GetCanvasRenderCamera(), // 使用正确的相机进行屏幕到局部坐标转换。
out localPoint // 输出的局部坐标。
);
// 添加转换后的局部坐标到点列表中。
points.Add(localPoint);
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
/// <summary>
/// 将鼠标的当前位置作为线条的末端点。
/// 该方法支持对已有折线的末端点进行修改,也可用于绘制“橡皮筋”效果。
/// </summary>
public void SetMouse()
{
// 如果点列表为空,则无法设置鼠标位置为末端点,直接返回。
if (points.Count == 0)
{
return;
}
var mousePosition = Input.mousePosition; // 获取当前的鼠标屏幕坐标。
Vector2 localPoint;
// 将鼠标屏幕坐标转换为当前UILineRenderer的局部坐标。
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, mousePosition, GetCanvasRenderCamera(), out localPoint);
if (points.Count == 1)
{
// 如果只有一个点,则将鼠标位置作为第二点添加到列表,形成第一条线段。
points.Add(localPoint);
}
else // points.Count >= 2
{
// 如果已有多个点,则更新列表中的最后一个点为鼠标位置。
points[points.Count - 1] = localPoint;
}
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
/// <summary>
/// 设置线的宽度。
/// </summary>
/// <param name="width">线条的新宽度。</param>
public void SetWidth(float width)
{
LineWidth = width; // 调用公共属性,确保 SetVerticesDirty() 被调用。
}
/// <summary>
/// 设置线条的渐变颜色。
/// </summary>
/// <param name="newGradient">新的渐变色对象。</param>
public void SetGradient(Gradient newGradient)
{
// 仅当新的渐变色不同于当前渐变色时才进行更新。
if (newGradient != null && !newGradient.Equals(lineGradient))
{
lineGradient = newGradient;
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
}
/// <summary>
/// 设置线条的起始和结束线头类型。
/// </summary>
/// <param name="startCapType">新的起始线头类型。</param>
/// <param name="endCapType">新的结束线头类型。</param>
public void SetCaps(LineCapType startCapType, LineCapType endCapType)
{
// 仅当线头类型发生改变时才更新。
if (startCap != startCapType || endCap != endCapType)
{
startCap = startCapType;
endCap = endCapType;
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
}
/// <summary>
/// 重置此UILineRenderer组件的状态包括清空所有点、重置宽度、渐变色和线头类型。
/// </summary>
public void ResetSelf()
{
points.Clear(); // 清空所有线条点。
// 重置为默认的纯白色渐变。
lineGradient = new Gradient();
lineGradient.SetKeys(
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) }
);
lineWidth = 5f; // 重置线条宽度为默认值。
startCap = LineCapType.None; // 重置线头类型为无。
endCap = LineCapType.None; // 重置线头类型为无。
SetVerticesDirty(); // 标记UI网格需要重新生成。
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a7c56ce7d0f247639e5fff6ebba2edd6
timeCreated: 1757415509