目标
有时在UI显示的时候,需要将原图片左右或者上下镜像显示。一种简单的方法就是将对应轴的scale参数设置为-1,但这种设置方式会导致子物体的scale也发生变化。为了避免对子物体的显示造成影响,这里利用改变图片顶点数据的方式来实现图片的镜像显示,最终效果如下。
实现
这里主要利用了UnityEngine.UI中的IMeshModifier接口,这个接口用于对UI中已构建好的顶点进行修改。只要编写一个实现了这个接口的组件,将其挂载在与Image同一个的GameObject下,我们就能随意修改顶点数据来达到想要的效果。 实现脚本如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Graphic))]
public class ImageMirror : MonoBehaviour, IMeshModifier
{
public enum Axis
{
Horizontal,
Vertical,
Center,
}
[SerializeField]
private Axis m_axis;
[SerializeField]
private bool m_on;
public Axis axis
{
get
{
return m_axis;
}
set
{
m_axis = value;
Graphic graphic = GetComponent<Graphic>();
if (graphic != null)
{
graphic.SetVerticesDirty();
}
}
}
void Awake()
{
Graphic graphic = GetComponent<Graphic>();
if (graphic == null)
{
DestroyImmediate(this);
return;
}
}
public void SetEnable(bool enable)
{
if (m_on != enable)
{
Graphic graphic = GetComponent<Graphic>();
if (graphic != null)
{
graphic.SetVerticesDirty();
}
m_on = enable;
}
}
public void ModifyMesh(Mesh mesh)
{
throw new System.NotImplementedException();
}
public void ModifyMesh(VertexHelper verts)
{
if (!m_on) return;
RectTransform rectTransform = GetComponent<RectTransform>();
Vector2 center = rectTransform.rect.center;
int vertCount = verts.currentVertCount;
for (int i = 0; i < vertCount; ++i)
{
UIVertex vertex = new UIVertex();
verts.PopulateUIVertex(ref vertex, i);
Vector3 position = vertex.position;
switch (m_axis)
{
case Axis.Horizontal:
position.x = 2 * center.x - position.x;
break;
case Axis.Vertical:
position.y = 2 * center.y - position.y;
break;
case Axis.Center:
position.x = 2 * center.x - position.x;
position.y = 2 * center.y - position.y;
break;
}
vertex.position = position;
verts.SetUIVertex(vertex, i);
}
}
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(ImageMirror))]
public class ImageMirrorEditor : UnityEditor.Editor
{
private ImageMirror instance;
private void Awake()
{
instance = target as ImageMirror;
}
public override void OnInspectorGUI()
{
UnityEditor.EditorGUI.BeginChangeCheck();
base.OnInspectorGUI();
if (UnityEditor.EditorGUI.EndChangeCheck())
{
Graphic graphic = instance.GetComponent<Graphic>();
graphic.SetVerticesDirty();
}
}
}
#endif
注意
这种方式改变顶点位置,可能会改变面的方向。一般来说,UI里都是双面渲染的,但如果的对面片的朝向有要求,就需要再修改一下三角形的索引顺序才行。
|