赞
踩
我们在创建可视UI组件时,可以通过继承Graphic来实现一些UI上的绘制功能。官方案例 中通过重写了 OnPopulateMesh 函数实现了一个绘制彩色四边形的效果。
利用该方法,结合一些对地形数据的处理,我们可以制作像下图这样的地形剖面图效果:
Graphic 是UGUI的核心组件,附件画面的显示。关于其原理,可以参考大佬博客,这里我们只谈谈几个小细节与关键步骤。
首先, UIVertex是用来管理UI顶点的一个结构体,我们可以将我们计算所得的顶点的位置信息存在这个结构体中(它是以像素为单位的)。
其次,右上角的剖面图上显示的变化的线其实是由诸多小矩形组成。我们在计算好顶点位置,给UIVertex赋值完之后,便可调用VertexHelper.AddUIVertexQuad(UIVertexs) 来将一个矩形加入到渲染中。
最后,我们需要调用刷新函数,SetAllDirty() 是分别设置Layout布局、Vertices顶点和Material材质为Dirty。我们这里只需要调用SetVerticesDirty()即可(每次修改参数都要调用其刷新)。
这边提供一个顶点数据设置的函数实现,另外的坐标轴、刻度线、坐标轴箭头等的实现方式类似。
[Header("坐标轴显示属性")] public float width = 200; public float height = 200; public float lineWidth = 5; public Vector2 offset = new Vector2(2, 2); [Header("坐标轴数据属性")] public Vector2 axleMaxValue = new Vector2(100, 100); public Vector2 axleMinValue = Vector3.zero; public List<Vector2[]> datas = new List<Vector2[]>(); /// <summary> /// 设置顶点属性 /// </summary> private void SetData(VertexHelper vh) { foreach (var data in datas) { Vector2[] pixelPoints = new Vector2[data.Length]; for (int i = 0; i < data.Length; i++) { pixelPoints[i].x = (data[i].x - axleMinValue.x) / axleMaxValue.x * width; pixelPoints[i].y = (data[i].y - axleMinValue.y) / axleMaxValue.y * height; pixelPoints[i] += offset; } UIVertex[] verts = new UIVertex[4]; for (int i = 0; i < verts.Length; i++) { verts[i].color = Color.blue; } for (int i = 0; i < pixelPoints.Length - 1; i++) { SetVerts(pixelPoints[i], pixelPoints[i + 1], lineWidth, verts); vh.AddUIVertexQuad(verts); } // 设置UI顶点数据 void SetVerts(Vector2 _start, Vector2 _end, float _width, UIVertex[] _verts) { Vector2[] tmp = GetRect(_start, _end, _width); _verts[0].position = tmp[0]; _verts[1].position = tmp[1]; _verts[2].position = tmp[3]; _verts[3].position = tmp[2]; } // 获取两点组成的矩形边框, 起始点,终止点,宽度 Vector2[] GetRect(Vector2 _start, Vector2 _end, float _width) { Vector2[] rect = new Vector2[4]; Vector2 dir = GetHorizontalDir(_end - _start); // 获取水平向右的向量 rect[0] = _start + dir * _width; rect[1] = _start - dir * _width; rect[2] = _end + dir * _width; rect[3] = _end - dir * _width; return rect; } } }
至于数据的获取,我这边是利用两点间的距离和方向,每隔一小段距离取一个点,获取其在地表的高度。以距离和高度组成vector2数组作为参数赋值给datas。下面是个获取data的函数实现。
/// <summary> /// 获取起点到终点的高度分析 /// </summary> /// <param name="start">起点</param> /// <param name="end">终点</param> /// <returns>x为对应点到起点的距离,y为对应点的高度</returns> public Vector2[] GetHeights(Vector3 start,Vector3 end) { float dis = Vector3.Distance(start, end); Vector3 dir = (end - start).normalized; int count = (int)dis / 5; Vector2[] result = new Vector2[count + 1]; for (int i = 0; i < count; i++) { Vector3 pos = TerrainUtility.GetPositionOnTerrain(start + dir * i * 5); result[i] = new Vector2(i * 5, pos.y); } result[count] = new Vector2(dis, TerrainUtility.GetPositionOnTerrain(end).y); return result; }
就酱。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。