問題描述
說到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);
}
}
}
參考文獻