Unity UGUI 绘制优雅的线段

Unity UGUI 绘制优雅的线段

引言

有时候,我们需要在unity中绘制线段,最常规的做法就是使用LineRenderer组件了。但有时候我们LineRenderer用起来并不那么适合,比如,我们需要在UI层绘制线段时,当然通过一系列的坐标转换,可以完美的将LineRenderer呈现在UI层,但总归不是很方便。这时候我们就可以自己写一些东西了。

MaskableGraphic

UI里面有这个类,只要我们重载它的OnPopulateMesh方法,就可以构造一些三角面,用于呈现任何形状。其实它很类似MeshFilter。主要用到两个方法:

VertexHelper.AddVert			// 添加顶点
VertexHelper.AddTriangle		// 添加三角面

构造线的思路

一段直线
与数学意义上的线不同,在数学上,一条线段由两个端点确定,但在unity中,我们的线段必须要有宽度,否则无法显示,最基本的线段要有四个顶点,2个3角面,如上图所示。
当我们给定线段的两个顶点时,计算4个顶点,并不难,只要知道线的宽度,通过一些方法很容易就能算出来,比如:

// 首先计算线的方向
Vector2 dir = EndPosition - StartPosition;

// 然后将方向旋转90°。
Vector2 left = (Quaternion.AngleAxis(90, Vector3.forward) * dir).normalized;

// 然后就可以计算出四个顶点:
Vector2 leftBottom = EndPostion + left * HalfLineWidth;
Vector2 rightBottom = EndPostion + ( - Left * HalfLineWidth );
Vector2 leftTop = StartPosition + left * HalfLineWidth;
Vector2 rightTop = StartPosition + ( - left * HalfLineWidth );

但是,实际中使用的线多半并不是直线,而是由很多点构成的线。那么就会存在问题:
2
如果使用上面的计算方法,在线段转弯的地方,无法避免两条线段的“弯外处”会出现缺口,而“弯内”处出现重叠。如何优雅的解决此问题呢。
我的思路是:
在这里插入图片描述
如上图所示,分别求两段的方向(蓝色虚线),然后转90°得到黄色虚线,求平均,得到粉色实线。线段宽度的一半,除以cos(α),就能得到边缘的交点。具体代码如下:

int count = positions.Count;
int csub1 = count - 1;
for (int i = 0; i < count; ++ i )
{
	int ia1 = i + 1;
	int is1 = i - 1;
	
	if( i == 0 )
	{
		// 处理第一个节点
	    FiristPoint(positions[i], positions[ia1], vh);
	}
	else if( i == csub1 )
	{
		// 处理最后一个节点
	    LastPoint(positions[is1], positions[i], vh);
	}
	else
	{
		// 处理中间的节点
	    MidPoint(positions[is1], positions[i], positions[ia1], vh);
	}
}

为了方便处理,分为三种情况进行处理,第一个节点没有前继节点,最后一个节点没有后继节点,单独拿出来处理一下,这样思路比较清晰。关键是中间的节点,按照上面的思路,代码如下:

/// <summary>
/// 处理中间节点
/// </summary>
/// <param name="prev">上一个顶点</param>
/// <param name="cur">当前顶点</param>
/// <param name="next">下一个顶点</param>
/// <param name="vh">顶点管理器</param>
private void MidPoint(Vector2 prev, Vector2 cur, Vector2 next, VertexHelper vh)
{
    Vector2 left1 = (orthogonality * (cur - prev)).normalized;
    Vector2 left2 = (orthogonality * (next - cur)).normalized;

    Vector2 left = ((left1 + left2) * 0.5f).normalized;
    float a = Vector2.Angle(left1, left2) * Mathf.Deg2Rad * 0.5f;

    float r = Radius / Mathf.Cos(a);

    vh.AddVert(cur + left * r, color, Vector2.zero);
    vh.AddVert(cur + left * -r, color, Vector2.zero);
}

然后就完成了,就可以所心所欲的在GUI上构造线段了。如下所示:

Unity UGUI MaskableGraphic绘制线段

继续完善

实际上可以完善的地方还有很多,但有了上面的基础,很容易就能扩充很多有意思的功能,比如,首尾节点可以搞成圆头状的,转弯的地方可以增加过度。还可以加入贝塞尔计算。最后,当然还可以设置每个顶点的UV!!在例子中没有去设置UV,但实际上AddVert方法支持UV设置。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
UnityGUIUnity游戏引擎中的一个GUI系统,它是一种基于对象的图形用户界面系统,用于在游戏中创建交互式的用户界面。它允许开发者创建按钮、文本框、滑块等交互元素,并通过事件和回调函数来处理用户的输入和交互。 UnityGUI的源码提供了UnityGUI系统的实现细节,可以用于了解和学习UnityGUI的工作原理。通过阅读源码,开发者可以理解UnityGUI是如何创建、渲染和处理UI元素的,以及它是如何与游戏场景和其他组件进行交互的。 在UnityGUI的源码中,可以找到一些核心的类和函数,比如GUI类、GUILayout类和GUIStyle类等。GUI类提供了一系列静态函数来创建和绘制UI元素,比如按钮、标签和文本框。GUILayout类则提供了一组函数来实现自动布局,以便更方便地创建复杂的UI布局。GUIStyle类则包含了一些样式信息,比如字体、颜色和边框等。 通过查看源码,可以了解到UnityGUI绘制原理和性能优化技巧。比如,可以看到UnityGUI是如何使用批处理技术将多个UI元素合并为一次渲染调用,以减少渲染开销。还可以了解到UnityGUI是如何处理用户的输入事件,并通过回调函数来实现相应的响应。 总之,UnityGUI的源码是一个宝贵的学习资源,可以帮助开发者更好地理解和使用UnityGUI系统。通过深入研究源码,开发者可以从中汲取经验和技巧,提高UI设计和开发的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

示申○言舌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值