Unity UGUI 效果 之 UI 元素 多边形UI (例如雷达图,圆形,不规则多边形 UI等)显示 的简单实现的几种方法整理
目录
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的方法。
二、可以自由调整形状的多边形 UI
1、功能说明
1)添加脚本 PolygonUIMesh
2)在该脚本的组建下,添加子物体,作为 Polygon 多边形的点
3)任意移动子物体,Polygon 多边形都会穗子变化
3、效果预览
3、 实现步骤
1)编写好脚本 PolygonUIMesh
2)挂在 PolygonUIMesh 脚本到 Canvas 下的物体上
(注意:PolygonUIMesh 相当于 Button 的 Image,所以可以在其组建上添加 Button,实现按钮功能等)
3)在挂载 PolygonUIMesh 脚本组件下,添加子物体,会自动作为多变形的点,移动他们既可以跳帧多边形形状了
4、关键代码
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);
}
}
}
三、调整对应边数,实现任意正多边形,甚至圆形 UI
1、功能介绍
1)这里是继承 RawImage,调整其多边形的绘制
2)改变边数,实现 UI 多边形
3)调整 UI 元素宽高,效果会有不一样(局限性)
2、效果预览
3、实现步骤
1)编写脚本 UIPolygonRawImage ,继承 RawImage ,重写其方法,实现多边形UI
(其中:UIPolygonRawImageInspector 脚本是对 UIPolygonRawImage 变量显示的调整,放在 Editor 目录下即可 )
(UIPolygonRawImageInspector 可以根据需要可要可不要,不影响功能)
2)在 Canvas 下添加组件,并挂载脚本 UIPolygonRawImage ,对应添加图片
(跟使用 RawImage差不多,只是多了个边数)
3)调整边数,实现多边形 UI
4、关键代码
参考博文: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);
}
}
四、类雷达图的多边形 UI
1、功能说明
1)查看UGUI的代码可以得知,绘制ui图的方法其实是绘制mesh,然后对其进行填充。正常一个Image图片,绘制有四个顶点。为了实现多边形,继承于MaskableGraphic,重写OnPopulateMesh,重新绘制顶点。
2)能调整边数,点的比例,是否填充,旋转等,控制显示雷达图的样式
2、效果预览
3、实现步骤
1)编写脚本,实现类雷达图的功能
2)把脚本挂载到Canvas 的组建下
3)调整脚本参数,即可根据需要调整成自己想要的样式
4、关键代码
参考博文: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;
}
}
}
五、类雷达图多边形UI(二)
参考博文:http://www.lsngo.net/2017/10/26/unity_polygonalui/
1、功能介绍
1)可以添加图线
2)可以调整边数,和点的比例,改变样式
2、效果预览
3、实现步骤
1)编写脚本 PolygonImage 等,实现功能
(注意有些脚本最好放在Editor 文件夹下)
2)把脚本 挂载到 Canvas 下的组件上
3)根据需要调整效果如上
4、关键代码
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, "边权重");
}
}
六、雷达图 UGUI 案例
1、效果图
2、Unity 场景布局
(这里的方法是通过改变黄色区域UI元素的外围顶点位置,来实现出我们需要的渲染效果。)
3、关键代码
(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);
}
}
}
最后,感谢各位博主。