文章说明
本篇文章基于NGUI (3.12.0)版本源码下的代码分析,如果代码和大家自己的不同,可能是版本不同。如果文章中分析有误希望大神看见指点迷津,大家好,我就是一个勤勤恳恳爱偷懒的码农,希望和大家一起学习研究。
自定义Panel
看这篇文章之前希望你把之前文章看过了,今天这一篇文章就是来做个实践操作吧,把之前关于 Panel 裁剪 的部分拆出来实现一个 demo,加深下对其的理解。
功能目标
我实现的功能非常简单,利用一张贴图模拟实现 UIPanel 如下功能:
1.实现 UIPanel 裁剪的 Soft Clip 功能,并且只实现单裁剪;
2.实现层级设置;
3.shader 直接使用 “Hidden/Unlit/Transparent Colored 1” ;
这里面涉及到功能主要有: mesh 创建,材质创建,给 shader 传递裁剪参数,将融合 UIPanel 和 UIDrawcall 部分功能。
代码
public static class ToolClass
{
public static T AddOrGetComponent<T>(this GameObject obj) where T : Component
{
T component = obj.GetComponent<T>();
if (null == component)
{
component = obj.AddComponent<T>();
}
return component;
}
}
public class NGUI_TestPanel : MonoBehaviour {
//外部属性
public Vector4 _ClipRange = new Vector4(0, 0, 300f, 200f);
public Vector2 _softness = new Vector2(5f, 5f);
public int depth = 0;
public Texture _tex;
//内部属性
private Vector4 _ShowRange = new Vector4(0, 0, 500f, 300f);
private MeshFilter _filter;
private MeshRenderer _render;
private Mesh _mesh;
private Material _mDynamicMat;
// Use this for initialization
void Start () {
}
private void OnEnable()
{
InitPanel();
}
private void InitPanel()
{
_filter = ToolClass.AddOrGetComponent<MeshFilter>(gameObject);
_render = ToolClass. AddOrGetComponent<MeshRenderer>(gameObject);
SetGeometryInfo();
SetMaterials();
SetClipping();
}
//只渲染一个面
private void SetGeometryInfo()
{
if (_mesh == null)
{
_mesh = new Mesh();
}
_mesh.hideFlags = HideFlags.DontSave;
_mesh.name = "NGUI_TestPanelMesh";
//设置几何信息
Vector3[] ver = { new Vector3(_ShowRange.x, _ShowRange.y),
new Vector3(_ShowRange.x, _ShowRange.w + _ShowRange.y, 0),
new Vector3(_ShowRange.z + _ShowRange.x, _ShowRange.w + _ShowRange.y, 0),
new Vector3(_ShowRange.z + _ShowRange.x, _ShowRange.y, 0)};
//int[] triangle = { 0, 1, 3, 1, 2, 3 };
int vertexCount = (ver.Length >> 1) * 3;
int[] triangle = new int[vertexCount];
int index = 0;
for (int i = 0; i < ver.Length; i += 4)
{
triangle[index++] = i;
triangle[index++] = i + 1;
triangle[index++] = i + 2;
triangle[index++] = i + 2;
triangle[index++] = i + 3;
triangle[index++] = i;
}
Vector2[] uv = { Vector2.zero, Vector2.up, new Vector2(1, 1), Vector2.right };
Vector3[] normal = { Vector3.back, Vector3.back, Vector3.back, Vector3.back };
//也可以不设置颜色
//Color[] color = { Color.white, Color.white, Color.white, Color.white};
_mesh.vertices = ver;
_mesh.uv = uv;
_mesh.triangles = triangle;
_mesh.normals = normal;
//_mesh.colors = color;
_filter.mesh = _mesh;
}
private void SetMaterials()
{
string shadername = "Hidden/Unlit/Transparent Colored 1";
Shader shader = Shader.Find(shadername);
if (_mDynamicMat == null)
{
_mDynamicMat = new Material(shader);
_mDynamicMat.name = "[NGUI] " + shadername;
_mDynamicMat.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
}
_mDynamicMat.mainTexture = _tex;
_mDynamicMat.renderQueue = 3000;
_render.sharedMaterials = new Material[] { _mDynamicMat };
_render.sortingOrder = depth;
}
private void SetClipping()
{
float angle = 0f;
angle*= -Mathf.Deg2Rad;
Vector2 sharpness = new Vector2(1000.0f, 1000.0f);
if (_softness.x > 0f) sharpness.x = _ClipRange.z / _softness.x;
if (_softness.y > 0f) sharpness.y = _ClipRange.w / _softness.y;
_mDynamicMat.SetVector("_ClipRange0", new Vector4(-_ClipRange.x / _ClipRange.z, -_ClipRange.y / _ClipRange.w,
1f/ _ClipRange.z, 1f/ _ClipRange.w));
_mDynamicMat.SetVector("_ClipArgs0", new Vector4(sharpness.x, sharpness.y, Mathf.Sin(angle), Mathf.Cos(angle)));
}
}
实际效果
我们分别创建了两个对象,分别挂载了 “NGUI_TestPanel” 这个组件,然后设置的参数如下:
最终运行后的效果如图所示: