Ugui Image控件绘制多个动态图

我们用一个Image控件,绘制多个动态图,效果如下



先说一下主要思路

我们创建一个Image控件会看到有个CanvasRenderer的组件,这个组件是负责渲染的。

首先我们准备一个图集


关于如何打图集,请参考我的上一篇文章

然后我们创建一个SpriteGraphicHelper.cs脚本这个脚本中主要有我们自定义的一个Mesh,我们将用这个mesh中的数据渲染图片,在自定义的Mesh中我们需要设置mesh.vertices顶点数据,是要在图片那些顶点上绘制,mesh.triangles顶点的三角形索引顺序,mesh.uv要绘制的图片在图集中的uv坐标。

然后我们创建一个脚本SpriteGraphic.cs继承自MaskableGraphic,MaskableGraphic方法中有UGUI具体绘制时的一些参数和方法,比如mainTexture属性是主纹理,这里我们设置为我们的图集.UGUI绘制时用到的Shader会总我们设置的mainTexture取值,然后我们调用MaskableGraphic中的UpdateMaterial刷新材质,一个图片就会支出来了。


我们想要绘制动态图片只需要在Update函数中把mesh.uv uv坐标改变即可,想要回执多个图片在mesh.vertices中传入多个顶点和每个顶点的uv值,然后给mesh.triangles顶点的三角形索引顺序赋值即可。

下面是具体的代码

首先是一个辅助类SpriteInfo.cs,用于存储每个小图片的一些信息

using UnityEngine;
using System.Collections;

public class SpriteInfo{
    /// <summary>
    /// 名称
    /// </summary>
    public string name;
    /// <summary>
    ///坐标&宽高
    /// </summary>
    public Rect rect;
    /// <summary>
    /// 精灵
    /// </summary>
    public Sprite sprite;
}


然后使我们的SpriteGraphicHelper.cs用于设置CanvasRenderer中的Mesh的

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SpriteGraphicHelper : MonoBehaviour {

    // Use this for initialization
    //图集
    public Texture2D texture2D;
    //单个小图的信息
    public List<SpriteInfo> m_sprites = new List<SpriteInfo>();
    //渲染器
    private CanvasRenderer m_spriteCanvasRenderer;
    //设置图片渲染的一些参数 比如主纹理 mainTexture
    private SpriteGraphic m_spriteGraphic;
    int index = 0;
    float time = 0;
    Rect rtRect;

    void Awake() {
        m_spriteCanvasRenderer = GetComponent<CanvasRenderer>();
        m_spriteGraphic = GetComponent<SpriteGraphic>();
        RectTransform rectTransform = GetComponent<RectTransform>();
        rtRect = rectTransform.rect;
    }

    void Start () {
        InitInfo();
    }
	
	// Update is called once per frame
	void Update () {
        time += Time.deltaTime;
        if (time > 0.3f) {
            if (index < m_sprites.Count)
            {
                DrawSprite(index);
                index++;
            }
            else
            {
                index = 0;
                DrawSprite(index);
            }
            time = 0;
        }
    }
    void InitInfo() {
        Object[] objs = Resources.LoadAll("Atlas");
        for (int i = 0; i < objs.Length; i++) {
            if(objs[i].GetType() == typeof(Texture2D)) {
                texture2D = objs[i] as Texture2D;
            }
            else if (objs[i].GetType() == typeof(Sprite)) {
                SpriteInfo info = new SpriteInfo();
                Sprite sprite = objs[i] as Sprite;
                info.name = sprite.name;
                info.rect = sprite.rect;
                info.sprite = sprite;
                m_sprites.Add(info);
            }
        }
        m_spriteGraphic.SetTexture(texture2D);
    }
    public  void DrawSprite(int index) {
        int imageWidth = 100;//图片宽度
        int imageHeight = 100;//图片高度

        Mesh mesh = new Mesh();
        Vector3[] vertices = new Vector3[8];
        Vector2[] uv = new Vector2[8];
        //设置第一个图片的uv值
        SpriteInfo spriteInfo = m_sprites[index];
        Rect rect = spriteInfo.rect;
        uv[0] = new Vector2(rect.x /(float)texture2D.width, rect.y / (float)texture2D.height);
        uv[1] = new Vector2(rect.x / (float)texture2D.width, (rect.y+rect.height) / (float)texture2D.height);
        uv[2] = new Vector2((rect.x+rect.width) / (float)texture2D.width, (rect.y+rect.height) / (float)texture2D.height);
        uv[3] = new Vector2((rect.x + rect.width) / (float)texture2D.width, rect.y / (float)texture2D.height);
        //设置第一个图片的顶点
        vertices[0] = new Vector3(rtRect.x, rtRect.y, 0);
        vertices[1] = new Vector3(rtRect.x, rtRect.y + imageHeight, 0);
        vertices[2] = new Vector3(rtRect.x + imageWidth, rtRect.y + imageHeight, 0);
        vertices[3] = new Vector3(rtRect.x + imageWidth, rtRect.y, 0);

        //设置第二个图片的uv值 这里为了和第一个图片显示的不同,选取了index的下一张图片
        if (index < m_sprites.Count - 1)
        {
            spriteInfo = m_sprites[index + 1];
            rect = spriteInfo.rect;
        }
        uv[4] = new Vector2(rect.x / (float)texture2D.width, rect.y / (float)texture2D.height);
        uv[5] = new Vector2(rect.x / (float)texture2D.width, (rect.y + rect.height) / (float)texture2D.height);
        uv[6] = new Vector2((rect.x + rect.width) / (float)texture2D.width, (rect.y + rect.height) / (float)texture2D.height);
        uv[7] = new Vector2((rect.x + rect.width) / (float)texture2D.width, rect.y / (float)texture2D.height);

        //设置第二个图片的顶点
        Vector2 startPos = new Vector2(rtRect.x+imageWidth,rtRect.y);
        vertices[4] = new Vector3(startPos.x, startPos.y, 0);
        vertices[5] = new Vector3(startPos.x, startPos.y + imageHeight, 0);
        vertices[6] = new Vector3(startPos.x + imageWidth, startPos.y + imageHeight, 0);
        vertices[7] = new Vector3(startPos.x + imageWidth, startPos.y, 0);

        //设置mesh
        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = new int[] { 0, 1, 2, 2, 3, 0,4,5,6,6,7,4};
        m_spriteCanvasRenderer.SetMesh(mesh);
        //刷新材质
        m_spriteGraphic.UpdateMaterial();
    }
    
}
然后是SpriteGraphic.cs,用于设置UGUI绘制时用到的主纹理mainTexture和刷新材质用的

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;

public class SpriteGraphic : MaskableGraphic
{
    private Texture2D texture2D;
    //主纹理
    public override Texture mainTexture
    {
        get
        {
            if (texture2D == null)
                return s_WhiteTexture;
            else
                return texture2D;
        }
    }
    //设置纹理
    public void SetTexture(Texture2D texture) {
        texture2D = texture;
    }
    /// <summary>
    /// 更新材质
    /// </summary>
    public new void UpdateMaterial()
    {
        base.UpdateMaterial();
    }

    protected override void OnEnable()
    {
        //调用base.OnEnable()第一帧会绘制出整个图片
        //base.OnEnable();
    }

}


我们在工程中创建一个Image控件,把Image控件上的的Image组件去掉,然后挂上SpriteGraphic.cs脚本和SpriteGraphicHelper.cs脚本。然后把我们大的图集Atlas放在Resources文件夹下,就可以实现上面的效果。


猜你喜欢

转载自blog.csdn.net/jk823394954/article/details/53931498