问题描述
说到Unity的检视面板编辑器扩展,相信大家都不会陌生。但是当你尝试用同样的方式去扩展UGUI的组件时,会发现根本没有效果。
解决方案
这个问题的解决方案有两个关键点:
用继承的方式避开同系统编辑器扩展的冲突
所扩展的编辑器类要继承ImageEditor类而不是Editor类
测试版本
Unity2018.4.0
前提条件
由于所要使用的ImageEditor类所在命名空间为UnityEditor.UI,而这个命名空间并不能直接敲出来。Unity一边的错误提示是程序集引用错误。这是一个坑点。
解决方法:需要手动将Unity安装路径Unity\Editor\Data\UnityExtensions\Unity\GUISystem\Editor 下的UnityEditor.UI.dll文件拷贝到当前项目的Assets文件夹的Plugins加下。
源代码
using UnityEngine.UI;
using UnityEngine.Sprites;
using UnityEngine;
public class CircletImage : Image
{
[SerializeField]
// 多少份三角形 拼成的圆形
int segements = 100;
//显示部分占圆形的百分比
[SerializeField]
float showPercent = 0.5f;
//需要绘制的顶点面片数据都存在了vh
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
float width = rectTransform.rect.width;
float height = rectTransform.rect.height;
int realsegments = (int)(segements * showPercent);
//先 引入 using UnityEngine.Sprites; 命名空间 再获取图片的外层的UV
//最好使用父类的overrideSprite 不使用sprite 具体因为啥我也不知道
Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
float uvWidth = (uv.z - uv.x);
float uvHeight = (uv.w - uv.y);
//获取UI中心
Vector2 uvCenter = new Vector2(uvWidth * 0.5f, uvHeight * 0.5f);
//求出于组件的宽高比
Vector2 convertRatio = new Vector2(uvWidth / width, uvHeight / height);
//单个三角形的弧度
float radian = (2 * Mathf.PI) / segements;
//获取半径
float radius = width * 0.5f;
//有了弧度 有了半径 就能求出 顶点的坐标 通过 Sin Cos 函数
//生成 顺时针 生成三角形 0 是中心点
Vector2 posTemp = Vector2.zero;
UIVertex origin = new UIVertex();
origin.color = color;
origin.position = posTemp;
// 换算UV坐标对应到Image中的位置 因为牵扯到Pivot 的0.5
origin.uv0 = new Vector2(posTemp.x * convertRatio.x + uvCenter.x, posTemp.y * convertRatio.y + uvCenter.y);
//添加顶点
vh.AddVert(origin);
//获取顶点的个数
int vertexCont = realsegments + 1;
float curRadian = 0;
for (int i = 0; i < vertexCont; i++)
{
//获取当前的顶点坐标
float x = Mathf.Cos(curRadian) * radius;
float y = Mathf.Sin(curRadian) * radius;
//累加 三角形弧度
curRadian += radian;
UIVertex vertexTemp = new UIVertex();
vertexTemp.color = color;
posTemp = new Vector2(x, y);
vertexTemp.position = posTemp;
// 换算UV坐标对应到Image中的位置 因为牵扯到Pivot 的0.5
vertexTemp.uv0 = new Vector2(posTemp.x * convertRatio.x + uvCenter.x, posTemp.y * convertRatio.y + uvCenter.y);
vh.AddVert(vertexTemp);
}
int id = 1;
for (int i = 0; i < realsegments; i++)
{
//生成 顺时针 生成三角形 0 是中心点 传入三个顶点 三个顶点是i , 0,i+1
vh.AddTriangle(id, 0, id + 1);
id++;
}
}
}
using UnityEngine;
using UnityEditor;
using UnityEditor.UI;
[CustomEditor(typeof(CircletImage), true)]
[CanEditMultipleObjects]
public class CircletImageEditor : ImageEditor
{
SerializedProperty _fillPercent;
SerializedProperty _segements;
protected override void OnEnable()
{
base.OnEnable();
_fillPercent = serializedObject.FindProperty("showPercent");
_segements = serializedObject.FindProperty("segements");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("测试按钮"))
{
}
serializedObject.Update();
EditorGUILayout.Slider(_fillPercent, 0, 1, new GUIContent("showPercent"));
EditorGUILayout.PropertyField(_segements);
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
EditorUtility.SetDirty(target);
}
}
}
参考文献