赞
踩
目录
Unity UGUI 效果 之 UI 元素 多边形UI (例如雷达图,圆形,不规则多边形 UI等)显示 的简单实现的几种方法整理
UGUI,是Unity自带的 GUI 系统,有别于 NGUI;使用 UGUI 也能制作出比较酷炫的效果 。
本节介绍,在 UGUI中 普通的 UI 元素中实现简单的多边形显示的若干方法的整理总结。
UGUI 的 UI 扩展,可参见 unity-ui-extensions 工程学习: https://bitbucket.org/ddreaper/unity-ui-extensions
接下来将逐一说明几种多边形UI的方法。
1)添加脚本 PolygonUIMesh
2)在该脚本的组建下,添加子物体,作为 Polygon 多边形的点
3)任意移动子物体,Polygon 多边形都会穗子变化
1)编写好脚本 PolygonUIMesh
2)挂在 PolygonUIMesh 脚本到 Canvas 下的物体上
(注意:PolygonUIMesh 相当于 Button 的 Image,所以可以在其组建上添加 Button,实现按钮功能等)
3)在挂载 PolygonUIMesh 脚本组件下,添加子物体,会自动作为多变形的点,移动他们既可以跳帧多边形形状了
- using UnityEngine;
- using System.Collections;
- using UnityEngine.UI;
-
- public class PolygonUIMesh : Graphic
- {
-
- private void OnGUI()
- {
- // 实时检测更新绘制 OnPopulateMesh 中 transform.child 位置
- SetAllDirty();
- }
-
- /// <summary>
- /// 根据 transform.child 位置 绘制 Mesh
- /// </summary>
- /// <param name="vh"></param>
- protected override void OnPopulateMesh(VertexHelper vh)
- {
- if (transform.childCount <= 2)
- {
- return;
- }
-
- Color32 color32 = color;
- vh.Clear();
-
- // 几何图形的顶点,本例中根据子节点坐标确定顶点
- foreach (Transform child in transform)
- {
- vh.AddVert(child.localPosition, color32, new Vector2(0f, 0f));
- }
-
- for (int i = 0; i < (transform.childCount-2); i ++)
- {
- // 几何图形中的三角形
- vh.AddTriangle(i+1, i + 2, 0);
-
- }
-
- }
-
- /// <summary>
- /// 点的辅助绘制
- /// </summary>
- private void OnDrawGizmos()
- {
- if (transform.childCount == 0)
- {
- return;
- }
-
- for (int i = 0; i < transform.childCount; i++)
- {
- Gizmos.DrawSphere(transform.GetChild(i).position, 2.55f);
- Gizmos.DrawIcon(transform.GetChild(i).position, "numbers/numbers_" + i+".PNG",false);
- }
-
- }
- }
1)这里是继承 RawImage,调整其多边形的绘制
2)改变边数,实现 UI 多边形
3)调整 UI 元素宽高,效果会有不一样(局限性)
1)编写脚本 UIPolygonRawImage ,继承 RawImage ,重写其方法,实现多边形UI
(其中:UIPolygonRawImageInspector 脚本是对 UIPolygonRawImage 变量显示的调整,放在 Editor 目录下即可 )
(UIPolygonRawImageInspector 可以根据需要可要可不要,不影响功能)
2)在 Canvas 下添加组件,并挂载脚本 UIPolygonRawImage ,对应添加图片
(跟使用 RawImage差不多,只是多了个边数)
3)调整边数,实现多边形 UI
参考博文:https://www.xuanyusong.com/archives/4375
1)UIPolygonRawImage
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
- public class UIPolygonRawImage : RawImage
- {
- const int FILL_PERCENT = 100;
- float thickness = 5;
-
- [SerializeField]
- [Range(4, 360)]
- int _segments = 36;
-
- public int segments
- {
- get { return _segments; }
- set
- {
- if (_segments != value)
- {
- _segments = value;
- SetVerticesDirty();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(transform);
- #endif
- }
- }
- }
-
-
- protected override void OnRectTransformDimensionsChange()
- {
- base.OnRectTransformDimensionsChange();
- this.thickness = (float)Mathf.Clamp(this.thickness, 0, rectTransform.rect.width / 2);
- }
-
- protected override void OnPopulateMesh(VertexHelper vh)
- {
- float outer = -rectTransform.pivot.x * rectTransform.rect.width;
- float inner = -rectTransform.pivot.x * rectTransform.rect.width + this.thickness;
-
- vh.Clear();
-
- Vector2 prevX = Vector2.zero;
- Vector2 prevY = Vector2.zero;
- Vector2 uv0 = new Vector2(0, 0);
- Vector2 uv1 = new Vector2(0, 1);
- Vector2 uv2 = new Vector2(1, 1);
- Vector2 uv3 = new Vector2(1, 0);
- Vector2 pos0;
- Vector2 pos1;
- Vector2 pos2;
- Vector2 pos3;
-
- float tw = rectTransform.rect.width;
- float th = rectTransform.rect.height;
-
- float angleByStep = (FILL_PERCENT / 100f * (Mathf.PI * 2f)) / segments;
- float currentAngle = 0f;
- for (int i = 0; i < segments + 1; i++)
- {
-
- float c = Mathf.Cos(currentAngle);
- float s = Mathf.Sin(currentAngle);
-
- StepThroughPointsAndFill(outer, inner, ref prevX, ref prevY, out pos0, out pos1, out pos2, out pos3, c, s);
-
- uv0 = new Vector2(pos0.x / tw + 0.5f, pos0.y / th + 0.5f);
- uv1 = new Vector2(pos1.x / tw + 0.5f, pos1.y / th + 0.5f);
- uv2 = new Vector2(pos2.x / tw + 0.5f, pos2.y / th + 0.5f);
- uv3 = new Vector2(pos3.x / tw + 0.5f, pos3.y / th + 0.5f);
-
- vh.AddUIVertexQuad(SetVbo(new[] { pos0, pos1, pos2, pos3 }, new[] { uv0, uv1, uv2, uv3 }));
-
- currentAngle += angleByStep;
- }
- }
-
- private void StepThroughPointsAndFill(float outer, float inner, ref Vector2 prevX, ref Vector2 prevY, out Vector2 pos0, out Vector2 pos1, out Vector2 pos2, out Vector2 pos3, float c, float s)
- {
- pos0 = prevX;
- pos1 = new Vector2(outer * c, outer * s);
-
- pos2 = Vector2.zero;
- pos3 = Vector2.zero;
-
- prevX = pos1;
- prevY = pos2;
- }
-
- protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs)
- {
- UIVertex[] vbo = new UIVertex[4];
- for (int i = 0; i < vertices.Length; i++)
- {
- var vert = UIVertex.simpleVert;
- vert.color = color;
- vert.position = vertices[i];
- vert.uv0 = uvs[i];
- vbo[i] = vert;
- }
- return vbo;
- }
- }
2)UIPolygonRawImageInspector
- using System.Collections;
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEditor.UI;
- using UnityEngine;
-
- [CustomEditor(typeof(UIPolygonRawImage), true)]
- [CanEditMultipleObjects]
- public class UIPolygonRawImageInspector : RawImageEditor
- {
- public override void OnInspectorGUI()
- {
- base.OnInspectorGUI();
- UIPolygonRawImage polygon = target as UIPolygonRawImage;
- polygon.segments = Mathf.Clamp(EditorGUILayout.IntField("UICircle多边形", polygon.segments), 4, 360);
-
- }
- }
1)查看UGUI的代码可以得知,绘制ui图的方法其实是绘制mesh,然后对其进行填充。正常一个Image图片,绘制有四个顶点。为了实现多边形,继承于MaskableGraphic,重写OnPopulateMesh,重新绘制顶点。
2)能调整边数,点的比例,是否填充,旋转等,控制显示雷达图的样式
1)编写脚本,实现类雷达图的功能
2)把脚本挂载到Canvas 的组建下
3)调整脚本参数,即可根据需要调整成自己想要的样式
参考博文:https://blog.csdn.net/u013012420/article/details/105956884
-
- using UnityEngine;
- using UnityEngine.UI;
-
- /// <summary>
- /// 雷达图
- /// </summary>
- public class RadarMapUIMesh : MaskableGraphic
- {
- public bool fill = true;
- public float thickness = 5;
- [Range(3, 360)]
- public int sides = 3;
- [Range(0, 360)]
- public float rotation = 0;
- [Range(0, 1)]
- public float[] VerticesDistances = new float[3];
- private float size = 0;
-
- public void DrawPolygon(int _sides)
- {
- sides = _sides;
- VerticesDistances = new float[_sides + 1];
- for (int i = 0; i < _sides; i++) VerticesDistances[i] = 1; ;
- rotation = 0;
- }
- public void DrawPolygon(int _sides, float[] _VerticesDistances)
- {
- sides = _sides;
- VerticesDistances = _VerticesDistances;
- rotation = 0;
- }
- public void DrawPolygon(int _sides, float[] _VerticesDistances, float _rotation)
- {
- sides = _sides;
- VerticesDistances = _VerticesDistances;
- rotation = _rotation;
- }
- void Update()
- {
- size = rectTransform.rect.width;
- if (rectTransform.rect.width > rectTransform.rect.height)
- size = rectTransform.rect.height;
- else
- size = rectTransform.rect.width;
- thickness = (float)Mathf.Clamp(thickness, 0, size / 2);
- }
-
- protected override void OnPopulateMesh(VertexHelper vh)
- {
- vh.Clear();
-
- Vector2 prevX = Vector2.zero;
- Vector2 prevY = Vector2.zero;
- Vector2 uv0 = new Vector2(0, 0);
- Vector2 uv1 = new Vector2(0, 1);
- Vector2 uv2 = new Vector2(1, 1);
- Vector2 uv3 = new Vector2(1, 0);
- Vector2 pos0;
- Vector2 pos1;
- Vector2 pos2;
- Vector2 pos3;
- float degrees = 360f / sides;
- int vertices = sides + 1;
- if (VerticesDistances.Length != vertices)
- {
- VerticesDistances = new float[vertices];
- for (int i = 0; i < vertices - 1; i++) VerticesDistances[i] = 1;
- }
- // last vertex is also the first!
- VerticesDistances[vertices - 1] = VerticesDistances[0];
- for (int i = 0; i < vertices; i++)
- {
- float outer = -rectTransform.pivot.x * size * VerticesDistances[i];
- float inner = -rectTransform.pivot.x * size * VerticesDistances[i] + thickness;
- float rad = Mathf.Deg2Rad * (i * degrees + rotation);
- float c = Mathf.Cos(rad);
- float s = Mathf.Sin(rad);
- uv0 = new Vector2(0, 1);
- uv1 = new Vector2(1, 1);
- uv2 = new Vector2(1, 0);
- uv3 = new Vector2(0, 0);
- pos0 = prevX;
- pos1 = new Vector2(outer * c, outer * s);
- if (fill)
- {
- pos2 = Vector2.zero;
- pos3 = Vector2.zero;
- }
- else
- {
- pos2 = new Vector2(inner * c, inner * s);
- pos3 = prevY;
- }
- prevX = pos1;
- prevY = pos2;
- SetVbo(new[] { pos0, pos1, pos2, pos3 }, new[] { uv0, uv1, uv2, uv3 });
- vh.AddUIVertexQuad(vbo);
- }
- }
- private UIVertex[] vbo = new UIVertex[4];
- private void SetVbo(Vector2[] vertices, Vector2[] uvs)
- {
- for (int i = 0; i < vertices.Length; i++)
- {
- var vert = UIVertex.simpleVert;
- vert.color = color;
- vert.position = vertices[i];
- vert.uv0 = uvs[i];
- vbo[i] = vert;
- }
- }
- }
参考博文:http://www.lsngo.net/2017/10/26/unity_polygonalui/
1)可以添加图线
2)可以调整边数,和点的比例,改变样式
1)编写脚本 PolygonImage 等,实现功能
(注意有些脚本最好放在Editor 文件夹下)
2)把脚本 挂载到 Canvas 下的组件上
3)根据需要调整效果如上
1)PolygonImage
- using UnityEngine;
- using UnityEngine.UI;
- using System.Collections.Generic;
-
- public class PolygonImage : MaskableGraphic, ISerializationCallbackReceiver, ICanvasRaycastFilter
- {
- [SerializeField]
- Texture m_Texture;
-
- public PolygonImageEdge edgeWeights;
-
- public override Texture mainTexture
- {
- get
- {
- if (m_Texture == null)
- {
- if (material != null && material.mainTexture != null)
- {
- return material.mainTexture;
- }
- return s_WhiteTexture;
- }
-
- return m_Texture;
- }
- }
-
- /// <summary>
- /// Texture to be used.
- /// </summary>
- public Texture texture
- {
- get
- {
- return m_Texture;
- }
- set
- {
- if (m_Texture == value)
- return;
-
- m_Texture = value;
- SetVerticesDirty();
- SetMaterialDirty();
- }
- }
-
- public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
- {
- if (raycastTarget)
- {
- Vector2 local;
- RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, sp, eventCamera, out local);
-
- int edgeCount = edgeWeights.EdgeCount;
-
- float deltaAngle = 360f/edgeCount;
-
- for (int i = 0; i < edgeCount; i++)
- {
- bool result = IsInPolygon(i, deltaAngle, local);
- if (result)
- return true;
- }
- }
- return false;
- }
-
- public virtual void OnAfterDeserialize()
- {
-
- }
-
- public virtual void OnBeforeSerialize()
- {
-
- }
-
- protected override void OnPopulateMesh(VertexHelper vh)
- {
- if (edgeWeights == null || edgeWeights.EdgeCount <= 2)
- {
- base.OnPopulateMesh(vh);
- return;
- }
- int edgeCount = edgeWeights.EdgeCount;
-
- float deltaAngle = 360f/edgeCount;
-
- vh.Clear();
-
- for (int i = 0; i < edgeCount; i++)
- {
- GetTriangle(vh, i, deltaAngle);
- }
- }
-
- private void GetTriangle(VertexHelper vh, int index, float deltaAngle)
- {
- float edgeLength = Mathf.Min(rectTransform.rect.width, rectTransform.rect.height)*0.5f;
- var color32 = color;
- Vector3 cent = new Vector3(0, 0);
- float angle1 = 90+(index + 1)*deltaAngle;
- float angle2 = 90+(index)*deltaAngle;
- float radius1 = (index == edgeWeights.EdgeCount - 1 ? edgeWeights.Weights[0] : edgeWeights.Weights[index + 1])* edgeLength;
- float radius2 = edgeWeights.Weights[index]*edgeLength;
-
- Vector3 p1 = new Vector3(radius1*Mathf.Cos(angle1*Mathf.Deg2Rad), radius1*Mathf.Sin(angle1*Mathf.Deg2Rad));
- Vector3 p2 = new Vector3(radius2 * Mathf.Cos(angle2 * Mathf.Deg2Rad), radius2 * Mathf.Sin(angle2 * Mathf.Deg2Rad));
-
- vh.AddVert(cent, color32, Vector2.zero);
- vh.AddVert(p1, color32, new Vector2(0,1));
- vh.AddVert(p2, color32, new Vector2(1,0));
-
- vh.AddTriangle(index*3, index*3 + 1, index*3 + 2);
- }
-
- private bool IsInPolygon(int index, float deltaAngle, Vector2 point)
- {
- float edgeLength = Mathf.Min(rectTransform.rect.width, rectTransform.rect.height)*0.5f;
- Vector2 cent = new Vector2(0, 0);
- float angle1 = 90+(index + 1) * deltaAngle;
- float angle2 = 90+(index) * deltaAngle;
- float radius1 = (index == edgeWeights.EdgeCount - 1 ? edgeWeights.Weights[0] : edgeWeights.Weights[index + 1])*edgeLength;
- float radius2 = edgeWeights.Weights[index]*edgeLength;
-
- Vector2 p1 = new Vector2(radius1 * Mathf.Cos(angle1 * Mathf.Deg2Rad), radius1 * Mathf.Sin(angle1 * Mathf.Deg2Rad));
- Vector2 p2 = new Vector2(radius2 * Mathf.Cos(angle2 * Mathf.Deg2Rad), radius2 * Mathf.Sin(angle2 * Mathf.Deg2Rad));
-
- return IsInTriangle(cent, p1, p2, point);
- }
-
- private bool IsInTriangle(Vector2 vertex1, Vector2 vertex2, Vector2 vertex3, Vector2 point)
- {
- Vector2 v0 =vertex3 - vertex1;
- Vector2 v1 = vertex2 - vertex1;
- Vector2 v2 = point - vertex1;
-
- float dot00 = Vector2.Dot(v0, v0);
- float dot01 = Vector2.Dot(v0, v1);
- float dot02 = Vector2.Dot(v0, v2);
- float dot11 = Vector2.Dot(v1, v1);
- float dot12 = Vector2.Dot(v1, v2);
-
- float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01);
-
- float u = (dot11 * dot02 - dot01 * dot12) * inverDeno;
- if (u < 0 || u > 1)
- {
- return false;
- }
-
- float v = (dot00 * dot12 - dot01 * dot02) * inverDeno;
- if (v < 0 || v > 1)
- {
- return false;
- }
-
- return u + v <= 1;
- }
- }
2)PolygonImageEdge
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
-
- [System.Serializable]
- public class PolygonImageEdge
- {
- public int EdgeCount
- {
- get
- {
- if (m_Weights == null)
- return 0;
- return m_Weights.Count;
- }
- }
-
- public List<float> Weights
- {
- get { return m_Weights; }
- }
-
- [SerializeField] private List<float> m_Weights;
-
- }
3)PolygonImageEditor
- using UnityEngine;
- using UnityEditor.UI;
- using UnityEditor;
- using UnityEditor.UI;
- using System.Collections;
-
- [CustomEditor(typeof(PolygonImage))]
- [CanEditMultipleObjects]
- public class PolygonImageEditor : GraphicEditor
- {
-
- private SerializedProperty m_Texture;
- private SerializedProperty m_EdgeWeights;
-
- protected override void OnEnable()
- {
- base.OnEnable();
- m_Texture = serializedObject.FindProperty("m_Texture");
- m_EdgeWeights = serializedObject.FindProperty("edgeWeights");
- }
-
- protected override void OnDisable()
- {
-
- }
-
- public override void OnInspectorGUI()
- {
- serializedObject.Update();
-
- EditorGUILayout.PropertyField(m_Texture);
- EditorGUILayout.PropertyField(m_Color);
- EditorGUILayout.PropertyField(m_Material);
- EditorGUILayout.PropertyField(m_RaycastTarget);
- EditorGUILayout.PropertyField(m_EdgeWeights);
-
- serializedObject.ApplyModifiedProperties();
- }
- }
4)PolygonImageEdgeDrawer
- using UnityEngine;
- using UnityEditor;
- using System.Collections;
- using UnityEditorInternal;
-
- [CustomPropertyDrawer(typeof(PolygonImageEdge))]
- public class PolygonImageEdgeDrawer : PropertyDrawer
- {
- private ReorderableList m_ReorderableList;
-
- private void Init(SerializedProperty property)
- {
- if (m_ReorderableList == null)
- {
- m_ReorderableList = new ReorderableList(property.serializedObject,
- property.FindPropertyRelative("m_Weights"));
- m_ReorderableList.drawElementCallback = DrawEdgeWeight;
- m_ReorderableList.drawHeaderCallback = DrawHeader;
- }
- }
-
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- Init(property);
- var val = EditorGUI.indentLevel;
- EditorGUI.indentLevel = 0;
- m_ReorderableList.DoList(position);
- EditorGUI.indentLevel = val;
- }
-
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- Init(property);
-
- return m_ReorderableList.GetHeight();
- }
-
- private void DrawEdgeWeight(Rect rect, int index, bool isActive, bool isFocused)
- {
- SerializedProperty itemData = m_ReorderableList.serializedProperty.GetArrayElementAtIndex(index);
- EditorGUI.Slider(rect, itemData, 0, 1);
- }
-
- private void DrawHeader(Rect rect)
- {
- EditorGUI.LabelField(rect, "边权重");
- }
- }
(这里的方法是通过改变黄色区域UI元素的外围顶点位置,来实现出我们需要的渲染效果。)
(Point是蓝色区域最外的顶点,只需执行一次获得其具体位置就行。Handler是红色的顶点,每次更新时都要同步更新)
1)Boke_RadarChart(黄色区域雷达图类)
- public class Boke_RadarChart : Image
-
- {
-
- //顶点个数、顶点位置、顶点大小、顶点显示图片、顶点颜色
-
- [SerializeField]
-
- private int _pointCount;
-
- [SerializeField]
-
- private List<RectTransform> _points;
-
- [SerializeField]
-
- private Vector2 _pointSize = new Vector2(10, 10);
-
- [SerializeField]
-
- private Sprite _pointSprite;
-
- [SerializeField]
-
- private Color _pointColor = Color.white;
-
-
-
- //每个方向上各个点的的比例、存储handler
-
- [SerializeField]
-
- private float[] _handlerRadio;
-
- [SerializeField]
-
- private List<S5RadarChartHandler> _handlers;
-
-
-
- private void Update()
-
- {
-
- //刷新
-
- SetVerticesDirty();
-
- }
-
-
-
- protected override void OnPopulateMesh(VertexHelper vh)
-
- {
-
- //修改原来的空image,让他填满我们的雷达图。
-
- //清空原来顶点,自己添加
-
- vh.Clear();
-
- AddVerts(vh);
-
- //AddVertsTemplete(vh);
-
- AddTriangle(vh);
-
- }
-
-
-
- /// <summary>
-
- /// 添加顶点
-
- /// </summary>
-
- private void AddVerts(VertexHelper vh)
-
- {
-
- //添加轴心点
-
- vh.AddVert(Vector3.zero, color, Vector2.zero);
-
- foreach (S5RadarChartHandler handler in _handlers)
-
- {
-
- vh.AddVert(handler.transform.localPosition, color, Vector2.zero);
-
- }
-
- }
-
-
-
- /*
-
- /// <summary>
-
- /// 如果需要用贴图。就要每个顶点单独设置uv坐标
-
- /// </summary>
-
- private void AddVertsTemplete(VertexHelper vh)
-
- {
-
- vh.AddVert(_handlers[0].transform.localPosition, color, new Vector2(0.5f, 1));
-
- vh.AddVert(_handlers[1].transform.localPosition, color, new Vector2(0f, 1));
-
- vh.AddVert(_handlers[2].transform.localPosition, color, new Vector2(0f, 0));
-
- vh.AddVert(_handlers[3].transform.localPosition, color, new Vector2(1f, 0));
-
- vh.AddVert(_handlers[4].transform.localPosition, color, new Vector2(1f, 1));
-
- }
-
- */
-
-
-
- /// <summary>
-
- /// 添加三角形
-
- /// </summary>
-
- private void AddTriangle(VertexHelper vh)
-
- {
-
- //围绕中心点生成5个面
-
- for (int i = 1; i < _pointCount; i++)
-
- {
-
- //用三个顶点组成一个三角面
-
- //顺时针
-
- vh.AddTriangle(0, i + 1, i);
-
- }
-
- vh.AddTriangle(0, _pointCount, 1);
-
- }
-
-
-
- public void InitPoint()
-
- {
-
- ClearPoints();
-
- _points = new List<RectTransform>();
-
- SpawnPoint();
-
- SetPointPos();
-
- }
-
-
-
- private void ClearPoints()
-
- {
-
- if (_points == null)
-
- return;
-
-
-
- foreach (RectTransform point in _points)
-
- {
-
- if (point != null)
-
- //编辑模式下要用这个
-
- DestroyImmediate(point);
-
- }
-
- }
-
-
-
- private void SpawnPoint()
-
- {
-
- //5个最边角的顶点
-
- for (int i = 0; i < _pointCount; i++)
-
- {
-
- GameObject point = new GameObject("Point" + i);
-
- point.transform.SetParent(transform);
-
- _points.Add(point.AddComponent<RectTransform>());
-
- }
-
- }
-
-
-
- private void SetPointPos()
-
- {
-
- //每个角的弧度
-
- float radian = 2 * Mathf.PI / _pointCount;
-
- //半径
-
- float radius = 100;
-
-
-
- //从最上面一个顶点开始算。以中心为原点。
-
- float curRadian = 2 * Mathf.PI / 4.0f;
-
- for (int i = 0; i < _pointCount; i++)
-
- {
-
- float x = Mathf.Cos(curRadian) * radius;
-
- float y = Mathf.Sin(curRadian) * radius;
-
- curRadian += radian;
-
- _points[i].anchoredPosition = new Vector2(x, y);
-
- }
-
- }
-
-
-
- public void InitHandlers()
-
- {
-
- ClearHandlers();
-
- _handlers = new List<S5RadarChartHandler>();
-
- SpawnHandlers();
-
- SetHandlerPos();
-
- }
-
-
-
- private void ClearHandlers()
-
- {
-
- if (_handlers == null)
-
- return;
-
-
-
- foreach (S5RadarChartHandler handler in _handlers)
-
- {
-
- if (handler != null)
-
- DestroyImmediate(handler.gameObject);
-
- }
-
- }
-
-
-
- private void SpawnHandlers()
-
- {
-
- S5RadarChartHandler handler = null;
-
- for (int i = 0; i < _pointCount; i++)
-
- {
-
- GameObject point = new GameObject("Handler" + i);
-
- point.AddComponent<RectTransform>();
-
- point.AddComponent<Image>();
-
-
-
- handler = point.AddComponent<S5RadarChartHandler>();
-
- handler.SetParent(transform);
-
- handler.ChangeSprite(_pointSprite);
-
- handler.ChangeColor(_pointColor);
-
- handler.SetSize(_pointSize);
-
- handler.SetScale(Vector3.one);
-
- _handlers.Add(handler);
-
- }
-
- }
-
-
-
- private void SetHandlerPos()
-
- {
-
- //默认的handler位置,就是5项属性全满。
-
- if (_handlerRadio == null || _handlerRadio.Length != _pointCount)
-
- {
-
- for (int i = 0; i < _pointCount; i++)
-
- {
-
- _handlers[i].SetPos(_points[i].anchoredPosition);
-
- }
-
- }
-
- else
-
- {
-
- for (int i = 0; i < _pointCount; i++)
-
- {
-
- _handlers[i].SetPos(_points[i].anchoredPosition * _handlerRadio[i]);
-
- }
-
- }
-
- }
-
- }
2)Boke_RadarChartHandler(红色顶点类)
- public class Boke_RadarChartHandler : MonoBehaviour
-
- {
-
- private Image _image;
-
- private Image Image
-
- {
-
- get
-
- {
-
- if (_image == null)
-
- _image = GetComponent<Image>();
-
-
-
- return _image;
-
- }
-
- }
-
-
-
- private RectTransform _rect;
-
- private RectTransform Rect
-
- {
-
- get
-
- {
-
- if (_rect == null)
-
- _rect = GetComponent<RectTransform>();
-
-
-
- return _rect;
-
- }
-
- }
-
-
-
- #region 封装一层
-
- public void SetParent(Transform parent)
-
- {
-
- transform.SetParent(parent);
-
- }
-
- public void ChangeSprite(Sprite sprite)
-
- {
-
- Image.sprite = sprite;
-
- }
-
- public void ChangeColor(Color color)
-
- {
-
- Image.color = color;
-
- }
-
- public void SetPos(Vector2 pos)
-
- {
-
- Rect.anchoredPosition = pos;
-
- }
-
- public void SetSize(Vector2 size)
-
- {
-
- Rect.sizeDelta = size;
-
- }
-
- public void SetScale(Vector3 scale)
-
- {
-
- Rect.localScale = scale;
-
- }
-
- private float GetScale()
-
- {
-
- return Rect.lossyScale.x;
-
- }
-
- #endregion
-
- }
3)Boke_RadarChartEditor
(编辑器类,用于把Boke_RadarChart类中的可变属性显示到面板中,方便我们更改调试。)
- using System.Collections;
-
- using System.Collections.Generic;
-
- using UnityEngine;
-
- using UnityEditor;
-
-
-
- [CustomEditor(typeof(Boke_RadarChart), true)]
-
- [CanEditMultipleObjects]
-
- public class Boke_RadarChartEditor : UnityEditor.UI.ImageEditor
-
- {
-
- SerializedProperty _pointCount;
-
- SerializedProperty _pointSprite;
-
- SerializedProperty _pointColor;
-
- SerializedProperty _pointSize;
-
- SerializedProperty _handlerRadio;
-
-
-
- protected override void OnEnable()
-
- {
-
- base.OnEnable();
-
- _pointCount = serializedObject.FindProperty("_pointCount");
-
- _pointSprite = serializedObject.FindProperty("_pointSprite");
-
- _pointColor = serializedObject.FindProperty("_pointColor");
-
- _pointSize = serializedObject.FindProperty("_pointSize");
-
- _handlerRadio = serializedObject.FindProperty("_handlerRadio");
-
- }
-
-
-
- public override void OnInspectorGUI()
-
- {
-
- base.OnInspectorGUI();
-
-
-
- serializedObject.Update();
-
-
-
- EditorGUILayout.PropertyField(_pointCount);
-
- EditorGUILayout.PropertyField(_pointSprite);
-
- EditorGUILayout.PropertyField(_pointColor);
-
- EditorGUILayout.PropertyField(_pointSize);
-
- EditorGUILayout.PropertyField(_handlerRadio,true);
-
-
-
- Boke_RadarChart radar = target as Boke_RadarChart;
-
- if (radar != null)
-
- {
-
- if (GUILayout.Button("生成雷达图顶点"))
-
- {
-
- radar.InitPoint();
-
- }
-
-
-
- if (GUILayout.Button("生成内部可操作顶点"))
-
- {
-
- radar.InitHandlers();
-
- }
-
- }
-
- serializedObject.ApplyModifiedProperties();
-
- if (GUI.changed)
-
- {
-
- EditorUtility.SetDirty(target);
-
- }
-
-
-
- }
-
- }
最后,感谢各位博主。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。