Ugui Image控制元件繪製多個動態圖
阿新 • • 發佈:2019-01-30
我們用一個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,用於儲存每個小圖片的一些資訊
然後使我們的SpriteGraphicHelper.cs用於設定CanvasRenderer中的Mesh的using UnityEngine; using System.Collections; public class SpriteInfo{ /// <summary> /// 名稱 /// </summary> public string name; /// <summary> ///座標&寬高 /// </summary> public Rect rect; /// <summary> /// 精靈 /// </summary> public Sprite sprite; }
然後是SpriteGraphic.cs,用於設定UGUI繪製時用到的主紋理mainTexture和重新整理材質用的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(); } }
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資料夾下,就可以實現上面的效果。