小编给大家分享一下UGUI如何绘制多点连续的平滑曲线,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
具体内容如下
绘制
实现自定义的MaskableGraphic挂载在UGUI的UI节点上
public class UGUIObjectRender : MaskableGraphic { /** * points 为需要穿过的点 * segments 为曲线细分度 * linewidth 为曲线粗细 */ protected override void OnPopulateMesh(VertexHelper vh) { vh.DrawBeziers(points,segments,linewidth); } }
需要时用的工具类在后面
二次贝塞尔工具类
using UnityEngine; namespace ViVi.UIExtensions { /** * Created by vivi on 16/5/11. */ public class BezierUtils { public float P0x; public float P1x; public float P2x; public float P3x; public float P0y; public float P1y; public float P2y; public float P3y; public BezierUtils(float p0x,float p0y,float p1x,float p1y,float p2x,float p2y,float p3x,float p3y) { P0x = p0x; P0y = p0y; P1x = p1x; P1y = p1y; P2x = p2x; P2y = p2y; P3x = p3x; P3y = p3y; } public BezierUtils(Vector2 p0,Vector2 p1,Vector2 p2,Vector2 p3) { P0x = p0.x; P0y = p0.y; P1x = p1.x; P1y = p1.y; P2x = p2.x; P2y = p2.y; P3x = p3.x; P3y = p3.y; } public float beze_x(float t){ float it = 1-t; return it*it*it*P0x + 3*it*it*t*P1x + 3*it*t*t*P2x + t*t*t*P3x; } public float beze_y(float t){ float it = 1-t; return it*it*it*P0y + 3*it*it*t*P1y + 3*it*t*t*P2y + t*t*t*P3y; } //------------------------------------------------------------------------------------- public float beze_speed_x(float t) { float it = 1-t; return -3*P0x*it*it + 3*P1x*it*it - 6*P1x*it*t + 6*P2x*it*t - 3*P2x*t*t + 3*P3x*t*t; } public float beze_speed_y(float t) { float it = 1-t; return -3*P0y*it*it + 3*P1y*it*it - 6*P1y*it*t + 6*P2y*it*t - 3*P2y*t*t + 3*P3y*t*t; } private float beze_speed(float t) { float sx = beze_speed_x(t); float sy = beze_speed_y(t); return (float) Mathf.Sqrt(Mathf.Pow(sx,2)+Mathf.Pow(sy,2)); } //------------------------------------------------------------------------------------- private float beze_length(float t) { float LATESTCOUNT = 10000; int steps = (int) Mathf.Ceil(LATESTCOUNT * t); if (steps == 0) return 0; if (steps % 2 != 0) steps++; float halfSteps = steps * .5f; float nSum = 0; float n1Sum = 0; float disStep = t / steps; for (int i = 0; i < halfSteps; i++ ) { n1Sum += beze_speed((2 * i + 1) * disStep); nSum += beze_speed(2 * i * disStep); } return (beze_speed(0) + beze_speed(1) + 2 * n1Sum + 4 * nSum) * disStep / 3; } //------------------------------------------------------------------------------------- private float beze_even(float t) { float len = t * beze_length(1); float uc = 0; do { float ulen = beze_length(t); float uspeed = beze_speed(t); uc = t - (ulen - len) / uspeed; if (Mathf.Abs(uc - t) < 0.0001) break; t = uc; }while(true); return uc; } private float totallength = -1; public float getTotalLength(){ if(totallength<0) totallength = beze_length(1); return totallength; } public Vector2 getPosition(float t){ return new Vector2(beze_x(t),beze_y(t)); } } }
UGUI 绘图工具类
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace ViVi.UIExtensions { public static class PolygonHelper { public static void AddUIVertexTriangles(this VertexHelper vh,UIVertex[] verts) { for (int i = 0; i < verts.Length; i += 3) { int currentVertCount = vh.currentVertCount; for (int index = i; index < i+3; index++) { vh.AddVert(verts[index].position, verts[index].color, verts[index].uv0, verts[index].uv1, verts[index].normal, verts[index].tangent); } vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); } } public static void AddUIVertexTriangle(this VertexHelper vh,UIVertex[] verts) { int currentVertCount = vh.currentVertCount; for (int index = 0; index < 3; ++index) vh.AddVert(verts[index].position, verts[index].color, verts[index].uv0, verts[index].uv1, verts[index].normal, verts[index].tangent); vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); } private static void vertex(this List<UIVertex> vertices,float x, float y , Color color) { UIVertex v = UIVertex.simpleVert; v.color = color; v.position = new Vector2(x,y); v.uv0 = Vector2.zero; } //画圆形 public static void circle (this VertexHelper vh, Vector2 pos, float radius,Color color,bool filled = false) { circle(vh,pos.x, pos.y, radius, Mathf.Max(1, (int)(6 * Mathf.Pow(radius,1/3f))),color,filled); } public static void circle (this VertexHelper vh, float x, float y, float radius,Color color,bool filled = false) { circle(vh,x, y, radius, Mathf.Max(1, (int)(6 * Mathf.Pow(radius,1/3f))),color,filled); } public static void circle (this VertexHelper vh, float x, float y, float radius, int segments ,Color color,bool filled = false) { if (segments > 0){ float angle = 2 * Mathf.PI / segments; float cos = Mathf.Cos(angle); float sin = Mathf.Sin(angle); float cx = radius, cy = 0; List<UIVertex> vs = new List<UIVertex>(); segments--; for (int i = 0; i < segments; i++) { vs.vertex(x, y, color); vs.vertex(x + cx, y + cy, color); float temp = cx; cx = cos * cx - sin * cy; cy = sin * temp + cos * cy; vs.vertex(x + cx, y + cy, color); } vs.vertex(x, y, color); vs.vertex(x + cx, y + cy, color); cx = radius; cy = 0; vs.vertex(x + cx, y + cy, color); vh.AddUIVertexTriangles(vs.ToArray()); } } public static void DrawBeziers(this VertexHelper vh,List<Vector2> points,float segment,float width) { List<BezierUtils> beziers = CreateBeziers(points); if (beziers != null) { for (int i = 0; i < beziers.Count; i++) { BezierUtils bezier = beziers[i]; DrawBezier(vh ,bezier,segment,width); } } } public static Vector2 nor (this Vector2 vec) { float len = vec.magnitude; if (len != 0) { vec.x /= len; vec.y /= len; } return vec; } public static Vector2 rotate90 (this Vector2 vec, int dir) { float x = vec.x; if (dir >= 0) { vec.x = -vec.y; vec.y = x; } else { vec.x = vec.y; vec.y = -x; } return vec; } public static Vector2 cpy (this Vector2 vec) { return new Vector2(vec.x,vec.y); } private static void DrawBezier(VertexHelper vh,BezierUtils bezier,float segment,float width) { List<Vector2> lpos = new List<Vector2>(); List<Vector2> rpos = new List<Vector2>(); for (int i = 0; i <= segment; i++) { Vector2 bezierPos = new Vector2(bezier.beze_x((float)i/(float)segment),bezier.beze_y((float)i/(float)segment)); Vector2 bezierSpeed = new Vector2(bezier.beze_speed_x((float)i/(float)segment),bezier.beze_speed_y((float)i/(float)segment)); Vector2 offseta = bezierSpeed.normalized.rotate90(1) * (0.5f * width); Vector2 offsetb = bezierSpeed.normalized.rotate90(-1) * (0.5f * width); lpos.Add(bezierPos.cpy() + offseta); rpos.Add(bezierPos.cpy() + offsetb); } for (int j = 0; j < segment; j++) { vh.AddUIVertexQuad(GetQuad(lpos[j], lpos[j+1], rpos[j+1], rpos[j])); } } private static UIVertex[] GetQuad (params Vector2[] vertPos) { UIVertex[] vs = new UIVertex[4]; Vector2[] uv = new Vector2[4]; uv[0] = new Vector2(0, 0); uv[1] = new Vector2(0, 1); uv[2] = new Vector2(1, 0); uv[3] = new Vector2(1, 1); for (int i = 0; i < 4; i++) { UIVertex v = UIVertex.simpleVert; v.color = Color.blue; v.position = vertPos[i]; v.uv0 = uv[i]; vs[i] = v; } return vs; } private static List<BezierUtils> CreateBeziers(List<Vector2> points) { float scale = 0.6f; List<BezierUtils> beziers = new List<BezierUtils>(); int originCount = points.Count - 1; List<Vector2> midpoints = new List<Vector2>(); for (int i = 0; i < originCount; i++) { midpoints.Add(new Vector2( Mathf.Lerp(points[i].x,points[i+1].x,0.5f), Mathf.Lerp(points[i].y,points[i+1].y,0.5f)) ); } List<Vector2> ctrlPoints = new List<Vector2>(); float offsetx; float offsety; ctrlPoints.Add(new Vector2( points[0].x, points[0].y )); for (int i = 0; i < originCount - 1; i++) { Vector2 orginPoint = points[i + 1]; offsetx = orginPoint.x - Mathf.Lerp(midpoints[i].x, midpoints[i + 1].x, 0.5f); offsety = orginPoint.y - Mathf.Lerp(midpoints[i].y, midpoints[i + 1].y, 0.5f); ctrlPoints.Add(new Vector2( midpoints[i].x + offsetx, midpoints[i].y + offsety )); ctrlPoints.Add(new Vector2( midpoints[i+1].x + offsetx, midpoints[i+1].y + offsety )); ctrlPoints[i * 2 + 1] = Vector2.Lerp(orginPoint, ctrlPoints[i * 2 + 1], scale); ctrlPoints[i * 2 + 2] = Vector2.Lerp(orginPoint, ctrlPoints[i * 2 + 2], scale); } ctrlPoints.Add(new Vector2( points[points.Count - 1].x, points[points.Count - 1].y )); for (int i = 0; i < originCount; i++) { BezierUtils bezier = getBezier(points[i], ctrlPoints[i * 2], ctrlPoints[i * 2 + 1],points[i + 1]); beziers.Add(bezier); } return beziers; } public static BezierUtils getBezier(Vector2 p0,Vector2 p1 ,Vector2 p2,Vector2 p3){ return new BezierUtils( p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); } } }
看完了这篇文章,相信你对“UGUI如何绘制多点连续的平滑曲线”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。