Unity中如何把Texture中的指定区域显示在Mesh对象上?
一、如何把下图数字按照1-16的先后顺序显示出来?
二、分析
在UGUI或者是NGUI中我们都会用到图集,图集就是把许多图片,通过一系列排序组合成一张图片;也就是多张图的使用变成对一张图片的使用,如果这里需要对上面这张图片分别显示单个数字,也就是按照从1-16或者随机显示任意一个数字该怎么显示呢?这里需要从以下几个方面入手:
- 首先需要知道该图片的大小【512*512】
- 每个数字所占区域的大小【128*128】
- 无论图片大小,图片的取值范围是0-1,也就是UV的坐标范围;
- 根据每个数字所占的大小和图片的宽高比例,计算出每个数字在Texture中的4个【左下角、左上角、右上角、右下角】UV坐标
- 计算出UV坐标以后,把对应的UV坐标赋值给对应的顶点,即可渲染显示出对应区域的像素图片
三、实例分析 如何计算出下图中数字6的4个UV坐标值
- 首先需要知道每个Mesh有2个三角形组成,6个顶点组成;但这里的数字6的Mesh共用1、3顶点【也可以通用4、2】,所以这里只需要计算出1234的对应UV坐标即可。
- 计算顶点1的UV坐标UV(1)=(128/512,128/512)
- 计算顶点2的UV坐标UV(2)=(128/512,256/512)
- 计算顶点3的UV坐标UV(3)=(256/512,256/512)
- 计算顶点4的UV坐标UV(4)=(256/512,128/512)
这样就计算出数字6的4个UV坐标,然后通过如下代码赋值即可:
List<Vector2> uvs = new List<Vector2>();
uvs.Add(leftBottomPoint);
uvs.Add(leftTopPoint);
uvs.Add(rightTopPoint);
uvs.Add(rightBottomPoint);
mesh.SetUVs(0, uvs);
四、动画效果演示
五、源码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ValakiUvDemo : MonoBehaviour
{
private Mesh mesh;
private MeshFilter meshFilter;
private float defaultImgWidth = 512;
private float defaultImgHeight = 512;
float characterWidth = 128;
float characterHeight = 128;
// Start is called before the first frame update
void Start()
{
CreateMesh();
StartCoroutine(DelayLoopIndex(0));
}
/// <summary>
/// 创建Mesh
/// </summary>
void CreateMesh()
{
meshFilter = gameObject.GetComponent<MeshFilter>();
mesh = new Mesh();
meshFilter.mesh = mesh;
int width = 10;
Vector3[] vertexts = new[]
{
new Vector3(0, 0, 10),
new Vector3(0, width, 10),
new Vector3(width, width, 10),
new Vector3(width, 0, 10),
};
int[] indices = new int[] {0, 1, 2, 0, 2, 3};
mesh.SetVertices(vertexts);
mesh.SetTriangles(indices, 0);
}
IEnumerator DelayLoopIndex(int index)
{
ShowImageByIndex(index);
yield return new WaitForSeconds(0.2f);
index++;
StartCoroutine(DelayLoopIndex(index));
}
/// <summary>
/// 根据索引显示UV图片
/// </summary>
/// <param name="index"></param>
void ShowImageByIndex(int index)
{
//uv的坐标是从左下角开始的 那么索引也是从0 开始
int rowIndex = index % 4;
int colIndex = index / 4;
//左下角
Vector2 leftBottomPoint = Vector2.zero;
leftBottomPoint.x = rowIndex * characterWidth / defaultImgWidth;
leftBottomPoint.y = colIndex * characterHeight / defaultImgHeight;
//左上角
Vector2 leftTopPoint = Vector2.zero;
leftTopPoint.x = leftBottomPoint.x;
leftTopPoint.y = (colIndex + 1) * characterHeight / defaultImgHeight;
//右上角
Vector2 rightTopPoint = Vector2.zero;
rightTopPoint.x = (rowIndex + 1) * characterWidth / defaultImgWidth;
rightTopPoint.y = leftTopPoint.y;
//右下角
Vector2 rightBottomPoint = Vector2.zero;
rightBottomPoint.x = rightTopPoint.x;
rightBottomPoint.y = leftBottomPoint.y;
List<Vector2> uvs = new List<Vector2>();
uvs.Add(leftBottomPoint);
uvs.Add(leftTopPoint);
uvs.Add(rightTopPoint);
uvs.Add(rightBottomPoint);
mesh.SetUVs(0, uvs);
}
}
结语
这个春节是确实冷,真真儿的叫冻成狗【valaki】