天天看点

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

首先来看看效果

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

https://www.zhihu.com/video/1221058687621615616

从视频中可以看出,图片可以被拖动,并且自动吸附到白色方框内,并且如果当目标区域有图片的时候,两个图片互换位置,接下来就让我们来实现这个效果。

首先新建一个项目,然后创建一个Panel,将其作为我们的背景,命名为BG

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

然后再在BG下创建image,命名为PicBg来作为摆放图片的地方,调整其大小,给PicBg添加上GridLayoutGroup组件。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

圈起来的地方是每个摆放方块的大小。

接下来创建一个Prefeb,作为摆放图片的地方。这个的思路是,用按钮创建这个Prefeb,然后再加上一个按钮作为摆放图片的父亲,图片作为第二曾按钮的子集,图片通过识别鼠标所在的父亲的位置来判断,这个不好表达,接下来就来实现它。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

Prefeb中的关系就是这样。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

接下来复制9个刚刚创建的Prefeb,并且统一命名为Slot,再通过GridLayoutGroup组件调整他们的位置。将PicBg的大小作调整,我想做成33并且中间留有3单位的空隙,而我的Slot长宽都为120,所以我的PicBg的大小应该为369*369。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

调整位置,接下来创建摆放图片位置的地点。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

将图片拖拽到PicPut下,并统一大小为120。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

效果如图

接下来要实现核心部分了。

首先是拖拽图片的代码,我们需要调用unity中的UnityEngine.EventSystems库,里面有三个接口,IBeginDragHandler, IDragHandler, IEndDragHandler。IBeginDragHandler是拖拽图片前,也就是鼠标点击图片的时候,IDragHandler是拖拽时,IEndDragHandler是拖拽后,我希望鼠标点击图片的时候,图片跟随鼠标,所以用这段代码。

public 
           

这样图片就会跟着鼠标移动了,但是我们会发现,图片会被其他东西所遮挡,那是因为Unity的渲染顺序导致的,所以我们此时应该变更图片的父节点,让图片不在被遮挡,然后不拖动图片的时候,图片回归原本的父节点。

代码修改成:

public 
           

使用这段代码后,图片就不会被遮挡了。

现在要来实现图片位置互换的问题。

首先再捋一下思路,我先创建了三层关系,图片->Item->Slot

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

要想调换图片的位置,我们就要确定目标图片的位置和本身图片的初始位置,我用他们的父亲来确定位置,然后更换图片自身的位置,也就相当于图片都更换了父亲,下面来举个例子,图片1要想换到图片2的位置,就首先上传自己父亲的位置,在获取图片2父亲的位置,获取到位置之后,在让图片1的位置变成图片2父亲的位置,让图片2的位置变成图片1父亲的位置,就这样两张图片被调换了位置。

注:Slot为同一个,而Item是其各自的父亲,也就是说Slot是两张图片的爷爷。

接下来就是代码实现,具体我就不讲解了,代码注释都有。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ItemChangePos : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public Transform orignaParent;
    public void OnBeginDrag(PointerEventData eventData)
    {
        orignaParent = transform.parent;//确定初始父节点
        transform.SetParent(transform.parent.parent.parent);//改变父节点
        transform.position = eventData.position;//让图片跟着鼠标移动
        GetComponent<CanvasGroup>().blocksRaycasts = false;
    }
    public void OnDrag(PointerEventData eventData)
    {
        transform.position = eventData.position;
        Debug.Log(eventData.pointerCurrentRaycast.gameObject.name);
    }

    public void OnEndDrag(PointerEventData eventData)
    {

        if (eventData.pointerCurrentRaycast.gameObject.name == "Image") //检测到目标对象为Image
        {
            transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform.parent); //将对象的父亲设为目标对象的父亲
            transform.position =
                eventData.pointerCurrentRaycast.gameObject.transform.parent.position; //将对象的位置变成目标对象父亲的位置
            eventData.pointerCurrentRaycast.gameObject.transform.SetParent(orignaParent); //改变目标对象的父亲为初始父亲
            eventData.pointerCurrentRaycast.gameObject.transform.position = orignaParent.position; //将目标对象的位置变成初始父亲的位置
            GetComponent<CanvasGroup>().blocksRaycasts = true;
            return;
        }
        else if (eventData.pointerCurrentRaycast.gameObject.name == "Item") //检测到目标对象为Item
        {
            transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform); //将此对象的父亲设置为目标对象的
            transform.position = eventData.pointerCurrentRaycast.gameObject.transform.position; //将此对象的位置设为目标对象的位置
            GetComponent<CanvasGroup>().blocksRaycasts = true;
            return;
        }

        transform.SetParent(orignaParent); //恢复父节点
        GetComponent<CanvasGroup>().blocksRaycasts = true;

    }
}
           

上面就是完整版的代码,我们将该脚本挂在图片上,就可以实现图片的拖拽和换位了。

漏了一个地方,就是Canvas Group组件,我们要将该组件挂在图片上,这样才能让图片知道下方是什么,在上面代码中,我通过Canvas Group组件发出的射线,知道了下方是Image或者Item,做出了不同效果。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)

就这样简单的拼图小游戏就大功告成啦。

unity transform_Unity的图片拖拽与摆放问题(实现简易拼图小游戏)