实现方式
1、引入UGUI自带的事件系统 UnityEngine.EventSystems
2、为我们的类添加接口 IBeginDragHandler, IDragHandler, IEndDragHandler
1 using UnityEngine; 2 using System.Collections; 3 using UnityEngine.EventSystems; 4 5 public class DragOnPic : MonoBehaviour,IBeginDragHandler, IDragHandler, IEndDragHandler { 6 7 8 public void OnBeginDrag (PointerEventData eventData) 9 { 10 throw new System.NotImplementedException (); 11 } 12 13 14 void IDragHandler.OnDrag (PointerEventData eventData) 15 { 16 throw new System.NotImplementedException (); 17 } 18 19 20 public void OnEndDrag (PointerEventData eventData) 21 { 22 throw new System.NotImplementedException (); 23 } 24 25 }
拼图游戏实例
1、准备一张拼图要用到的图片素材,并拖入Unity中
2、图片的TextureType选为Sprite(2D and UI), 点击Apply
3、将SpriteMode改为Multiple,点击SpriteEditor,在弹出的窗口中点Slice,Type为Grid,我这张图片分辨率是500x500的,拆分为16份,所以我的PixelSize是125x125,最终结果如下图:
4、添加一个Panel作为背景,为Panel添加GridLayoutGroup组件,具体设置如下,添加脚本ImageCreater用于生成图片
5、为Panel添加一个Image作为我们拼图的格子的背景,名字改为Cell,在这个Cell上再添加一个Image作为图片的载体,并将它的Tag设置为Cell,为Image添加拖拽脚本DragOnPic,将Cell拖成预制体备用
6、新建一个GameManager类用于实现随机生成图片的功能
1 public class GameManager { 2 3 /// <summary> 4 /// Randoms the array. 5 /// </summary> 6 static public void RandomArray(Sprite[] sprites) 7 { 8 for (int i = 0; i < sprites.Length; i++) { 9 //随机抽取数字中的一个位置,并将这张图片与第i张图片交换. 10 int index = Random.Range(i, sprites.Length); 11 Sprite temp = sprites[i]; 12 sprites[i] = sprites[index]; 13 sprites[index] = temp; 14 } 15 } 16 }
7、在ImageCreater中写入生产图片的方法
1 using UnityEngine; 2 using System.Collections; 3 using UnityEngine.UI; 4 5 public class ImageCreater : MonoBehaviour { 6 7 public static ImageCreater _instance; 8 9 //存储裁剪好图片的数组. 10 public Sprite[] sprites; 11 12 //格子的预设体. 13 public GameObject cellPrefab; 14 15 void Start () { 16 _instance = this; 17 CreateImages(); 18 } 19 20 private void CreateImages() 21 { 22 //将图片数组随机排列. 23 GameManager.RandomArray(sprites); 24 25 //生产图片. 26 for (int i = 0; i < sprites.Length; i++) { 27 //通过预设体生成图片. 28 GameObject cell = (GameObject)Instantiate(cellPrefab); 29 30 //设置cell的名字方便检测是否完成拼图. 31 cell.name = i.ToString(); 32 33 //获取cell的子物体. 34 Transform image = cell.transform.GetChild(0); 35 36 //设置显示的图片. 37 image.GetComponent<Image>().sprite = sprites[i]; 38 39 //设置子物体的名称,方便检测是否完成拼图. 40 int tempIndex = sprites[i].name.LastIndexOf('_'); 41 image.name = sprites[i].name.Substring(tempIndex + 1); 42 43 //将Cell设置为Panel的子物体. 44 cell.transform.SetParent(this.transform); 45 46 //初始化大小. 47 cell.transform.localScale = Vector3.one; 48 } 49 } 50 51 }
8、到这里,拼图游戏已经基本成形,下面只需要实现每张图片的拖拽功能就OK了,下面是DragOnPic的代码
1 using UnityEngine; 2 using System.Collections; 3 using UnityEngine.EventSystems; 4 5 public class DragOnPic : MonoBehaviour,IBeginDragHandler, IDragHandler, IEndDragHandler { 6 7 //记录下自己的父物体. 8 Transform myParent; 9 10 //Panel,使拖拽是显示在最上方. 11 Transform tempParent; 12 13 CanvasGroup cg; 14 RectTransform rt; 15 16 //记录鼠标位置. 17 Vector3 newPosition; 18 19 void Awake() 20 { 21 //添加CanvasGroup组件用于在拖拽是忽略自己,从而检测到被交换的图片. 22 cg = this.gameObject.AddComponent<CanvasGroup>(); 23 24 rt = this.GetComponent<RectTransform>(); 25 26 tempParent = GameObject.Find("Canvas").transform; 27 } 28 29 30 31 32 /// <summary> 33 /// Raises the begin drag event. 34 /// </summary> 35 public void OnBeginDrag (PointerEventData eventData) 36 { 37 //拖拽开始时记下自己的父物体. 38 myParent = transform.parent; 39 40 //拖拽开始时禁用检测. 41 cg.blocksRaycasts = false; 42 43 this.transform.SetParent(tempParent); 44 } 45 46 /// <summary> 47 /// Raises the drag event. 48 /// </summary> 49 void IDragHandler.OnDrag (PointerEventData eventData) 50 { 51 //推拽是图片跟随鼠标移动. 52 RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, Input.mousePosition, eventData.enterEventCamera, out newPosition); 53 transform.position = newPosition; 54 } 55 56 /// <summary> 57 /// Raises the end drag event. 58 /// </summary> 59 public void OnEndDrag (PointerEventData eventData) 60 { 61 //获取鼠标下面的物体. 62 GameObject target = eventData.pointerEnter; 63 64 //如果能检测到物体. 65 if(target) 66 { 67 GameManager.SetParent(this.transform, target.transform, myParent); 68 } 69 else { 70 this.transform.SetParent (myParent); 71 this.transform.localPosition = Vector3.zero; 72 } 73 74 //拖拽结束时启用检测. 75 cg.blocksRaycasts = true; 76 77 //检测是否完成拼图. 78 if(GameManager.CheckWin()) 79 { 80 Debug.Log("Win!!!"); 81 } 82 83 } 84 85 }
在GameManager中加入设置父物体的方法及检测是否完成拼图的方法:
1 /// <summary> 2 /// Sets the parent. 3 /// </summary> 4 static public void SetParent(Transform mine, Transform target, Transform oldParent) 5 { 6 //如果检测到图片,则交换父物体并重置位置. 7 switch (target.tag) 8 { 9 case "Cell": 10 mine.SetParent(target.parent); 11 target.SetParent(oldParent); 12 mine.localPosition = Vector3.zero; 13 target.localPosition = Vector3.zero; 14 break; 15 default: 16 mine.SetParent (oldParent); 17 mine.localPosition = Vector3.zero; 18 break; 19 } 20 } 21 22 /// <summary> 23 /// Checks is win. 24 /// </summary> 25 static public bool CheckWin() 26 { 27 for (int i = 0; i < ImageCreater._instance.transform.childCount; i++) { 28 if(ImageCreater._instance.transform.GetChild(i).name != ImageCreater._instance.transform.GetChild (i).transform.GetChild(0).name) 29 { 30 return false; 31 } 32 } 33 return true; 34 }
到这里,拼图的基本功能就算是全部完成了