1. 程式人生 > >Ugui Image控制元件繪製多個動態圖

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資料夾下,就可以實現上面的效果。