本人也是个0基础的开发人员,这里仅仅是作为一个学习的总结,假设哪里的理解错了,欢迎纠正。
帧动画的实现能够用第三方的插件,相似2DToolkit。能够非常easy的实现帧动画,但有时还是不要太过于依赖第三方的插件。有时间还是得自己研究怎样实现,不能一直穿着别人的内裤啊~
这个是本次项目的终于效果图:
关于在Unity3d下怎样用代码生成面,这里雨松MOMO已经有相关的博文:
http://www.xuanyusong.com/archives/780
理解下一张Material的坐标系,这里用了网上找的一张图片:
每一个Material都有自己的这个坐标系。
而假设须要把一张纹理贴到一个面上,则须要把贴图上的UV坐标(UV坐标就是上面的坐标系)相应到面的每一个顶点上,如图(又是网上的图片):
比方有以下一张图片:
图片总宽高为:192x152,单张精灵的宽高为48x38;
假设我们仅仅想显示左上角的1张图片。代码例如以下
using UnityEngine;
using System.Collections;
public class ViewImage : MonoBehaviour {
public int widthCount , heightCount;
//图片的宽高比例//
public float width = 48,height = 38;
//素材贴图//
public Material material;
//顶点数//
private int verticesCount = 4;
private Vector2 size;
private Mesh mesh;
public int frameIndex = 0;
private MeshRenderer meshRenderer;
// Use this for initialization
void Start () {
initFace();
}
/// <summary>
/// 初始化一个面
/// </summary>
private void initFace(){
//得到MeshFilter对象//
MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
if(meshFilter == null){
//为null时,自己主动加入//
meshFilter = gameObject.AddComponent<MeshFilter>();
meshRenderer = gameObject.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = material;
}
//得到相应的网格对象//
mesh = meshFilter.mesh;
//三角形顶点的坐标数组//
Vector3[] vertices = new Vector3[verticesCount];
//得到三角形的数量//
int trianglesCount = verticesCount - 2;
//三角形顶点数组//
int[] triangles = new int[verticesCount *3];
float tmpWidth = 1.0f;
float tmpHeight = 1.0f ;
vertices[0] = new Vector3(0,0,0);
vertices[1] = new Vector3(0,tmpHeight,0);
vertices[2] = new Vector3(tmpWidth,0,0);
vertices[3] = new Vector3(tmpWidth,tmpHeight,0);
mesh.vertices = vertices;
/*
*
* 假设以下的顶点连线看不明确,看这里
triangles[0] = 0;
triangles[1] = 1;
triangles[2] = 2;
triangles[3] = 1;
triangles[4] = 3;
triangles[5] = 2;
*/
//起始三角形顶点//
int start = 0;
//结束三角形的顶点//
int end = 2;
for(int i = start; i <end; i++)
{
for(int j = 0; j < 3; j++)
{
if( i%2 ==0)
{
triangles[3*i + j] = i +j;
}else
{
triangles[3*i + j] = i + 2-j;
}
}
}
mesh.triangles = triangles;
Vector3 localScale = new Vector3(width,height,1.0f);
transform.localScale = localScale;
size = new Vector2 (1.0f / widthCount , 1.0f / heightCount);
setUVPosition(frameIndex,mesh);
}
//设置uv坐标
private void setUVPosition(int index,Mesh mesh){
//得到相对于图片的行列坐标//
int uIndex = index % widthCount; //列坐标//
int vIndex = index / heightCount; //行坐标//
//左下角的坐标点;//
Vector2 vertices0 = new Vector2 (uIndex * size.x, 1.0f - size.y - vIndex * size.y);
//左上角坐标//
Vector2 vertices1 = new Vector2(vertices0.x , vertices0.y + size.y);
//右下角坐标//
Vector2 vertices2 = new Vector2(vertices0.x + size.x , vertices0.y );
//右上角坐标//
Vector2 vertices3 = new Vector2(vertices0.x + size.x , vertices0.y + size.y);
mesh.uv = new Vector2[]{vertices0 , vertices1 , vertices2 , vertices3};
}
}
代码上面都有凝视,这里关于用图片的素材球的Shader说明下,一開始我用Transparent/Diffuse,可是在执行时。切换uv坐标时控制台打印了Shader wants normals, but the mesh doesn't have them 这个消息。
Google下也不知道为什么,最后用Unlit/Transparent就没有打印了,所以哪位大神知道原因告诉我下~~
继续,如今已经能够从一张大贴图中显示当中的一张图片了。接下来整理成动画就是把这些帧图片整合在一起。在Update里头切换就KO了,代码例如以下:
//控制动画帧数//
public int[] aniArray;
void Update(){
if(Time.frameCount % 8 == 0){
int len = aniArray.Length;
int curIndex = aniArray[frameIndex];
setUVPosition(curIndex,mesh);
frameIndex ++;
frameIndex %= len;
}
}
以下是项目的一张截图,用红线圈起来的部分是动画帧的下标数组。
WidgetCount:大贴图x方向上有多少张图片。
HeightCount:大贴图y方向上有多少张图片。
Width:分隔的小贴图的宽度。
Height:f分隔的小贴图的高度。
FrameIndex:当前播放到第几帧的下标。
Ani Array:帧动画的下标集合数组。
O了。这篇事实上好早就在写,但一直没去完毕..今天光棍就顺便完毕掉~