【Unity】新的UI系统技巧

发表于2018-10-18
评论0 2.5k浏览
从Unity4.6开始,集成了新的UI系统。这篇文章将记录新的UI系统的一些使用技巧,分享给大家,希望大家可以将学到的这些知识应用到自己在做的项目中去。

1、给人物加血条效果

把要挂载的父节点的RectTransform中的锚点设置位buttonLeft。并获得当前的Canvas中的CanvasScaler,计算出缩放因子(比如下面是按照y来进行缩放的)
CanvasScaler scaler = GetComponent<CanvasScaler> ();
if(scaler != null) {
    float s = scaler.referenceResolution.y / Screen.height;
    UIScaleFactor = Vector3.one * s;  // 初始化缩放因子, 因为本游戏是按照高度来缩放的,所以这里是y的缩放因子
} 
else 
{
    Debug.LogError("[UIBattle] Cannot get component of CanvasScaler!");       
}
var pos = Camera.main.WorldToScreenPoint(BloodBarPos);  // 获取屏幕地址
pos.Scale(UIScaleFactor);  // 进行缩放
bloodTrans.anchoredPosition = pos;  // 设置位置,当然这个bloodTrans在某个锚点在ButtonLeft的父节点下

2、定制一个雷达图控件


代码如下:
using System.Collections;
using UnityEngine.UI;
[ExecuteInEditMode]
public class RadarChart : Graphic {
	public RectTransform[] maxPoints;
	private float[] percents = new float[5] { 1, 1, 1, 1, 1 };
    private Vector3[] vertexes = new Vector3[6];
	private bool isDirty = true;
	void Update() {
		#if UNITY_EDITOR
		isDirty = true;
		#endif
		if(isDirty) {
			isDirty = false;
			refresh();
		}
	}
	public void refresh() {
		vertexes[0] = maxPoints[0].anchoredPosition;
		for(int i=1; i<maxPoints.Length; i++) {
			vertexes[i] = maxPoints[0].anchoredPosition + (maxPoints[i].anchoredPosition - maxPoints[0].anchoredPosition)*percents[i-1];
		}
		SetAllDirty();
	}
	public float perA {
		get {
			return percents[0];
		}
		set {
			percents[0] = Mathf.Clamp01(value);
			isDirty = true;
		}
	}
	public float perB {
		get {
			return percents[1];
		}
		set {
			percents[1] = Mathf.Clamp01(value);
			isDirty = true;
		}
	}
	public float perC {
		get {
			return percents[2];
		}
		set {
			percents[2] = Mathf.Clamp01(value);
			isDirty = true;
		}
	}
	public float perD {
		get {
			return percents[3];
		}
		set {
			percents[3] = Mathf.Clamp01(value);
			isDirty = true;
		}
	}
	public float perE {
		get {
			return percents[4];
		}
		set {
			percents[4] = Mathf.Clamp01(value);
			isDirty = true;
		}
	}
    protected override void OnPopulateMesh(Mesh m)
    {
        var r = GetPixelAdjustedRect();
        var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
        Color32 color32 = color;
        using (var vh = new VertexHelper())
        {
            foreach (Vector3 p in vertexes)
            {
                vh.AddVert(p, color32, Vector2.zero);
            }
            vh.AddTriangle(2, 0, 1);
            vh.AddTriangle(3, 0, 2);
            vh.AddTriangle(4, 0, 3);
            vh.AddTriangle(5, 0, 4);
            vh.AddTriangle(1, 0, 5);
            vh.FillMesh(m);
        }
    }
}

编辑器代码:
using UnityEditor;
using UnityEngine;
using System.Collections;
[CustomEditor(typeof(RadarChart))]
public class RadarChartEditor : Editor {
	SerializedProperty maxPointsProp, color, raycast, material;
	SerializedProperty percents;
	string[] names ;
	void OnEnable() {
		maxPointsProp = serializedObject.FindProperty("maxPoints");
		percents = serializedObject.FindProperty("percents");
		color = serializedObject.FindProperty("m_Color");
		raycast = serializedObject.FindProperty("m_RaycastTarget");
		material = serializedObject.FindProperty("m_Material");
		names = new string[6] {
			"Center", "ATK", "HP", "ASS", "REV", "CON" 
		};
	}
	bool showMaxProp = false, showPercent = true;
	public override void OnInspectorGUI() {
		serializedObject.Update ();
		showMaxProp = EditorGUILayout.Foldout(showMaxProp, "Max Points");
		if(showMaxProp) {
			int size = maxPointsProp.arraySize;
			for(int i=0; i<size; i++) {
				SerializedProperty p = maxPointsProp.GetArrayElementAtIndex(i);
				EditorGUILayout.PropertyField(p, new GUIContent(names[i], ""));
			}
		}
		EditorGUILayout.PropertyField(raycast);
		EditorGUILayout.PropertyField(material);
		EditorGUILayout.PropertyField(color);
		EditorGUILayout.Space();
		showPercent = EditorGUILayout.Foldout(showPercent, "percents");
		if(showPercent) {
			int size = percents.arraySize;
			for(int i=0; i<size; i++) {
				SerializedProperty p = percents.GetArrayElementAtIndex(i);
				EditorGUILayout.Slider(p, 0, 1, new GUIContent(names[i+1], ""));
			}
		}
		serializedObject.ApplyModifiedProperties ();
	}
}

3、定制属性面板

官方有一个很不错的例子:http://docs.unity3d.com/ScriptReference/Editor.html
把Property暴露到面板上:http://wiki.unity3d.com/index.php?title=Expose_properties_in_inspector
详细的Editor例子:http://catlikecoding.com/unity/tutorials/editor/custom-list/
http://catlikecoding.com/unity/tutorials/editor/custom-data/
Editor高阶例子:http://catlikecoding.com/unity/tutorials/editor/star/

4、定制一个刻度条相关的控件

如下:

基本原理是继承Graphic类,并重写OnPopulateMesh函数,用到一些基本的OpenGL画矩形的算法。比较有参考的是制作控件的习惯和编辑器的使用,从而使工程模块化,提供工作效率。

代码如下:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
public class BloodBar : Graphic {
    public float _bloodNum = 7; 
    public float bloodNum {
        get {
            return _bloodNum;
        }
        set {
            _bloodNum = value;
            if(_bloodNum < 1) {
                _bloodNum = 1;
                Debug.LogWarningFormat("The number should not less than 1!");
            }
            SetAllDirty();
        }
    }
    private float lineWidth = 1f;
    private float deltaWidth = 1;
    /// <summary>
    /// Update the UI renderer mesh.
    /// </summary>
    protected override void OnPopulateMesh(VertexHelper vh) {
        Rect r = GetPixelAdjustedRect();
        deltaWidth = r.width / bloodNum;
        Vector2 offset = new Vector2(r.xMin, r.yMin);
        vh.Clear();
        for(int i = 0; i < bloodNum-1; i++) {
            drawLine(vh, r, offset, i);
        }
    }
    private void drawLine(VertexHelper vh, Rect r, Vector2 offset, int idx) {
        float pos = (idx + 1) * deltaWidth;
        int ti = idx * 4;
        float p = (idx + 1) % 5 == 0 ? 0 : 0.4f;
        vh.AddVert(new Vector2(pos,             r.height*p) + offset, Color.black, Vector2.zero);
        vh.AddVert(new Vector2(pos + lineWidth, r.height*p) + offset, Color.black, Vector2.zero);
        vh.AddVert(new Vector2(pos + lineWidth, r.height) + offset, Color.black, Vector2.zero);
        vh.AddVert(new Vector2(pos,             r.height) + offset, Color.black, Vector2.zero);
        vh.AddTriangle(0 + ti, 1 + ti, 2 + ti);
        vh.AddTriangle(2 + ti, 3 + ti, 0 + ti);
    }
} 

编辑器代码:
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(BloodBar))]
public class BloodBarEditor : Editor {
    SerializedProperty bloodNum;
    void OnEnable() {
        bloodNum = serializedObject.FindProperty("_bloodNum");
    }
    public override void OnInspectorGUI() {
        serializedObject.Update();
        //DrawDefaultInspector();
        //BloodBar btns = (BloodBar)target;
        //btns.bloodNum = EditorGUILayout.Slider(btns.bloodNum, 0, 30);
        EditorGUILayout.Slider(bloodNum, 1, 30, new GUIContent("blood Num"));
        serializedObject.ApplyModifiedProperties();
    }
}
来自:https://blog.csdn.net/stalendp/article/details/42621917

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引