Unity3d制作简单拼图游戏 | 您所在的位置:网站首页 › 平面乐高拼图怎么拼的 › Unity3d制作简单拼图游戏 |
本文为原创,如需转载请注明原址:http://blog.csdn.net/cube454517408/article/details/7907247
最近一直在使用Unity,对它有了一些小的使用心得 今天写一个简单的拼图游戏实例来和大家分享一下Unity中material.mainTextureOffset和material.mainTextureScale的作用和用法
mainTextureOffset和mainTextureScale是Material类中的两个方法 mainTextureOffset指的是主纹理偏移 mainTextureScale指的是主纹理缩放 默认一个material的mainTextureOffset是0,0,mainTextureScale是1,1 表示原图正常显示,没有缩放,如下图 当我们改变mainTextureScale的值时纹理只会显示一部分,其范围是[0,1]; 如我们将mainTextureScale.x设置为0.5时,可以看到纹理只显示u方向的50%
同理,我们将mainTextureScale.y设置为0.5时,可以看到纹理只显示v方向的50%
mainTextureOffset属性表示纹理的起始偏移,为0时没有偏移,mainTextureOffset.x指u方向的偏移量,mainTextureOffset.y指v方向的偏移量。其范围也是[0,1]。这里要注意:偏移的起点在图像的左下角 我们设置mainTextureOffset.x为0.2,如下图: 可以看到纹理向左偏移了20%
我们设置mainTextureOffset.y为0.2,如下图: ![]() 可以看到纹理向下偏移了20%
应用这两个属性,我们可以只截取图片的一部分来显示,如: mainTextureOffset = new Vector2(0.5, 0.5); mainTextureScale= new Vector2(0.5, 0.5); 将只显示原图的右上角1/4区域,如下图:
有了对以上两个属性的了解,我们可以来制作一个简单的拼图游戏 思路: 1.将一张图片切分为raw*volumn的raw*volumn张碎片 2.每一张碎片只显示图片的一部分 3.将它们按一个顺序和位置排列,使其看起来像一张完整的图片 玩法: 点击Start按钮后,开始游戏。选中碎片并将其拖放在正确的位置上,如放置正确则不可再被拖动。直到所有碎片放置正确。 点击Next Texture按钮可切换背景和碎片显示的图片
制作流程: 新建一个游戏场景Test,设置摄像机属性如下(采用正交摄像机(2D)将其标签设置MainCamera): 创建两个plane,其中一个改名为Background并为其选择一个材质;另一个plane也选择一个材质要和前一个不同,选择shader为Unlit/Transparent (自发光),将其设为不可见。创建一个空对象,起名为Body,如下图: 创建一个c#脚本main.cs,绑定在Body对象下。Inspector设置如下: main.cs脚本如下: using UnityEngine; using System.Collections; public class main : MonoBehaviour { public GameObject _plane; //用来实例碎片的对象 public GameObject _planeParent; //碎片对象所要绑定的父节点 public GameObject _background; //显示暗色的背景图 public Texture2D[] _texAll; //用来更换的纹理 public Vector3[] _RandomPos; //开始时, 碎片随机分布的位置 public int raw = 3; //图形切分的行数 public int volumn = 3; //图形切分的列数 public float factor = 0.25f; //一个范围比例因子, 用来判断碎片是否在正确位置范围内 GameObject[] _tempPlaneAll; float sideLength = 0; //背景图的边长(正方形) int finishCount = 0; //完成的碎片数量 int _index = 0; Vector2 originPoint; //第一个碎片的位置 Vector2 space; //碎片与碎片之间的间隔(中心距x,y) void Start() { sideLength = _background.transform.localScale.x; space.x = sideLength / volumn; space.y = sideLength / raw; originPoint.x = -((volumn - 1) * space.x) / 2; originPoint.y = ((raw - 1) * space.y) / 2; Vector2 range; range.x = space.x * factor * 10f; range.y = space.y * factor * 10f; _tempPlaneAll = new GameObject[raw * volumn]; int k = 0; //完成所有碎片的有序排列位置和uv纹理的截取 for(int i = 0 ; i != raw ; ++i) { for(int j = 0 ; j != volumn ; ++j) { GameObject tempObj = (GameObject)Instantiate(_plane); tempObj.name = "Item" + k; tempObj.transform.parent = _planeParent.transform; tempObj.transform.localPosition = new Vector3((originPoint.x + space.x * j) * 10f, (originPoint.y - space.y * i) * 10f, 0); tempObj.transform.localScale = new Vector3(space.x, 1f, space.y); Vector2 tempPos = new Vector2(originPoint.x + space.x * j, originPoint.y - space.y * i); float offset_x = (tempPos.x //将所有碎片随机分布在左右两边 for(int i = 0 ; i != _tempPlaneAll.Length ; ++i) { int tempRank = Random.Range(0, _RandomPos.Length); _tempPlaneAll[i].transform.localPosition = new Vector3(_RandomPos[tempRank].x, _RandomPos[tempRank].y, 0f); } //通知所有子对象, 开始游戏 gameObject.BroadcastMessage("Play"); } void SetIsMoveFale() { gameObject.BroadcastMessage("IsMoveFalse"); } void IsFinish() { //计算放置正确的碎片数量 ++finishCount; if(finishCount == raw * volumn) Debug.Log("Finish!"); } void ChangeTex() { _background.renderer.material.mainTexture = _texAll[_index]; gameObject.BroadcastMessage("SetTexture", _texAll[_index++]); if(_index > _texAll.Length - 1) _index = 0; } }
再创建一个c#脚本为plane.cs,绑定在Plane对象下。Inspector设置如下: 注意:要为Plane对象添加一个Collider组件,因为Plane对象的scale与Unity的基本单位(米)的比例为10:1,因此这里Collider的Size要设置为10 plane.cs脚本如下: using UnityEngine; using System.Collections; public class plane : MonoBehaviour { Transform mTransform; Vector3 offsetPos; //鼠标点与所选位置的偏移 Vector3 finishPos = Vector3.zero; //当前碎片的正确位置 Vector2 range; //碎片正确位置的范围, 由SetRange函数设置 float z = 0; bool isPlay = false; //是否进行游戏? bool isMove = false; //当前碎片是否跟随鼠标移动 void Start() { mTransform = transform; finishPos = mTransform.localPosition; } void Update() { if(!isPlay) return ; //当鼠标进入碎片中按下时, 记录与碎片中心位置的偏差; 并使碎片跟随鼠标移动(多张碎片叠在一起时,只选其中一张跟随) Vector3 tempMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); if(Input.GetMouseButtonDown(0) && tempMousePos.x > collider.bounds.min.x && tempMousePos.x < collider.bounds.max.x && tempMousePos.y > collider.bounds.min.y && tempMousePos.y < collider.bounds.max.y) { mTransform.parent.SendMessage("SetIsMoveFale"); offsetPos = mTransform.position - tempMousePos; z = mTransform.position.z; isMove = true; } //跟随鼠标移动 if(isMove && Input.GetMouseButton(0)) { tempMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mTransform.position = new Vector3(tempMousePos.x + offsetPos.x, tempMousePos.y + offsetPos.y, z - 0.1f); } //鼠标放开后停止跟随 if(Input.GetMouseButtonUp(0)) { mTransform.position = new Vector3(mTransform.position.x, mTransform.position.y, z); isMove = false; } //判断是否到达正确位置(如进入正确位置范围, 碎片自动设置在正确位置, 并不可被再移动) IsFinish(); } void IsFinish() { if(mTransform.localPosition.x > finishPos.x - range.x && mTransform.localPosition.x < finishPos.x + range.x && mTransform.localPosition.y > finishPos.y - range.y && mTransform.localPosition.y < finishPos.y + range.y) { isPlay = false; mTransform.localPosition = finishPos; mTransform.parent.SendMessage("IsFinish"); } } //开始游戏 void Play() { isPlay = true; } void IsMoveFalse() { isMove = false; } void SetRange(Vector2 _range) { range = _range; } //更换纹理 void SetTexture(Texture2D _tex) { mTransform.renderer.material.mainTexture = _tex; } }
现在可以开始游戏了,如下图:
程序源码及打包文件在此下载:http://download.csdn.net/detail/cube454517408/4525682 使用方法:打开一个空Unity场景,点击Assets->Import Package->Custom Package导入即可。注意:不要有中文路径
|
CopyRight 2018-2019 实验室设备网 版权所有 |