算是第一篇非转载的文章了~
在这里推荐个Unity3d很多功能效果的脚本集合的网站,也是部门老大发现给我的~
http://wiki.unity3d.com/index.php?title=Scripts/General
本人也是个初级的开发者,这里只是作为一个学习的总结,如果哪里的理解错了,欢迎纠正。
帧动画的实现可以用第三方的插件,类似2DToolkit,可以很容易的实现帧动画,但有时还是不要太过于依赖第三方的插件。有时间还是得自己研究如何实现,不能一直穿着别人的内裤啊~
这个是本次项目的最终效果图:
关于在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了,这篇其实好早就在写,但一直没去完成..今天光棍就顺便完成掉~