Unity使用碰撞开发类拖拽拼图逻辑
前言
在进行之前的项目时候,有一个需求就是做一个拖拽Image组件做一个类似于拼图游戏的逻辑。由于我之前开发过一个拼图的游戏,本来想利用判断位置开发这个功能,后来我突发奇想,可不可以通过碰撞实现这个拖拽的功能。花了几天时间,我实现了这个功能,不说了,先直接上效果图:
效果图1:
效果图2:
效果图3:
开发步骤
1.创建RankColliderManager.cs脚本,使用bool值记录碰撞状态,核心代码如下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Function;
public class RankColliderManager : MonoBehaviour
{
#region 参数
/// <summary>
/// 存储拖拽类
/// </summary>
public bool[] isHaveCard;
#endregion
#region 私有方法
/// <summary>
/// 碰撞检测
/// </summary>
/// <param name="other"></param>
void OnTriggerEnter2D(Collider2D other)
{
if (!isHaveCard[0])
{
if (other.gameObject.name == "frameToImage")
{
isHaveCard[0] = true;
}
}
if (!isHaveCard[1])
{
if (other.gameObject.name == "frameToImage0")
{
isHaveCard[1] = true;
}
}
if (!isHaveCard[2])
{
if (other.gameObject.name == "frameToImage1")
{
isHaveCard[2] = true;
}
}
if (!isHaveCard[3])
{
if (other.gameObject.name == "frameToImage2")
{
isHaveCard[3] = true;
}
}
if (!isHaveCard[4])
{
if (other.gameObject.name == "frameToImage3")
{
isHaveCard[4] = true;
}
}
if (!isHaveCard[5])
{
if (other.gameObject.name == "frameToImage4")
{
isHaveCard[5] = true;
}
}
if (!isHaveCard[6])
{
if (other.gameObject.name == "frameToImage5")
{
isHaveCard[6] = true;
}
}
}
/// <summary>
/// 离开检测
/// </summary>
void OnTriggerExit2D(Collider2D other)
{
if (isHaveCard[0])
{
if (other.gameObject.name == "frameToImage")
{
isHaveCard[0] = false;
}
}
if (isHaveCard[1])
{
if (other.gameObject.name == "frameToImage0")
{
isHaveCard[1] = false;
}
}
if (isHaveCard[2])
{
if (other.gameObject.name == "frameToImage1")
{
isHaveCard[2] = false;
}
}
if (isHaveCard[3])
{
if (other.gameObject.name == "frameToImage2")
{
isHaveCard[3] = false;
}
}
if (isHaveCard[4])
{
if (other.gameObject.name == "frameToImage3")
{
isHaveCard[4] = false;
}
}
if (isHaveCard[5])
{
if (other.gameObject.name == "frameToImage4")
{
isHaveCard[5] = false;
}
}
if (isHaveCard[6])
{
if (other.gameObject.name == "frameToImage5")
{
isHaveCard[6] = false;
}
}
}
#endregion
}
2.将此脚本挂载到拖拽区域物体上,添加bool数组值,添加BoxCollider2D组件,设置如图所示:
3.创建UIDragThis.cs脚本,它的功能主要是实现拖拽已经碰撞触发移动到位置效果等,核心代码如下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using Function;
using PlaneManager;
namespace RankManager
{
public class UIDragThis : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler
{
#region 参数
[Header("是否精确拖拽")]
internal bool m_isPrecision;
//存储图片中心点与鼠标点的偏移量
private Vector3 m_offset;
//存储当前拖拽图片的RectTransform组件
private RectTransform m_rt;
//是否可以拖动
internal bool canMove = true;
//自身起始位置
public Vector3 thisPosition;
//自身的id
public int thisID = 0;
//拖动组件父物体
public Transform content;
//碰撞物体数组
public RankColliderManager[] rankColliderManager;
#endregion
#region 常规方法
void Start()
{
//初始化
m_rt = gameObject.GetComponent<RectTransform>();
}
#endregion
#region 公共方法
public void OnBeginDrag(PointerEventData eventData)
{
//this.transform.parent = otherThis;
this.transform.SetParent(otherThis);
if (canMove)
{
//如果精确拖拽则进行计算偏移量操作
if (m_isPrecision)
{
//存储点击时的鼠标坐标
Vector3 tWorldPos;
//UI屏幕坐标转换为世界坐标
RectTransformUtility.ScreenPointToWorldPointInRectangle(m_rt, eventData.position, eventData.pressEventCamera, out tWorldPos);
//计算偏移量
m_offset = transform.position - tWorldPos;
}
//否则,默认偏移量为0
else
{
m_offset = Vector3.zero;
}
SetDraggedPosition(eventData);
}
}
/// <summary>
/// 拖拽过程中触发
/// </summary>
/// <param name="eventData"></param>
public void OnDrag(PointerEventData eventData)
{
if (canMove)
{
SetDraggedPosition(eventData);
}
}
/// <summary>
/// 结束拖拽触发
/// </summary>
/// <param name="eventData"></param>
public void OnEndDrag(PointerEventData eventData)
{
if (canMove)
{
SetDraggedPosition(eventData);
ChangePosition();
}
}
#endregion
#region 私有方法
/// <summary>
/// 设置图片位置方法
/// </summary>
/// <param name="eventData"></param>
private void SetDraggedPosition(PointerEventData eventData)
{
//存储当前鼠标所在的位置
Vector3 globalMousePos;
//UI屏幕坐标转换为世界坐标
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_rt,eventData.position,eventData.pressEventCamera,out globalMousePos))
{
m_rt.position = m_offset + globalMousePos;
}
}
/// <summary>
/// 判断改变自身位置
/// </summary>
void ChangePosition()
{
if (thisID == 0)
{
if (rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
!rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
!rankColliderManager[0].isHaveCard[5])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[5])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && !rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[5])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 1)
{
if (!rankColliderManager[0].isHaveCard[0] && rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
!rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
!rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && !rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 2)
{
if (!rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
!rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5]&&
!rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && !rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 3)
{
if (!rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && rankColliderManager[0].isHaveCard[3]&&
!rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
!rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && !rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 4)
{
if (!rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
!rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
rankColliderManager[2].isHaveCard[4] && !rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 5)
{
if (!rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
!rankColliderManager[0].isHaveCard[4] && rankColliderManager[0].isHaveCard[5] &&
!rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && rankColliderManager[1].isHaveCard[5] &&
!rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && rankColliderManager[2].isHaveCard[5] &&
!rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
if (thisID == 6)
{
if (!rankColliderManager[0].isHaveCard[0] && !rankColliderManager[0].isHaveCard[1] &&
!rankColliderManager[0].isHaveCard[2] && !rankColliderManager[0].isHaveCard[3] &&
!rankColliderManager[0].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
rankColliderManager[0].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 220.0f, 0f);
}
else if (!rankColliderManager[1].isHaveCard[0] && !rankColliderManager[1].isHaveCard[1] &&
!rankColliderManager[1].isHaveCard[2] && !rankColliderManager[1].isHaveCard[3] &&
!rankColliderManager[1].isHaveCard[4] && !rankColliderManager[1].isHaveCard[5] &&
rankColliderManager[1].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 150.0f, 0f);
}
else if (!rankColliderManager[2].isHaveCard[0] && !rankColliderManager[2].isHaveCard[1] &&
!rankColliderManager[2].isHaveCard[2] && !rankColliderManager[2].isHaveCard[3] &&
!rankColliderManager[2].isHaveCard[4] && !rankColliderManager[0].isHaveCard[5] &&
rankColliderManager[2].isHaveCard[6])
{
m_rt.localPosition = new Vector3(0f, 80.0f, 0f);
}
else
{
ToRecoverPosition();
}
}
/// <summary>
/// 恢复原始位置
/// </summary>
void ToRecoverPosition()
{
m_rt.localPosition = thisPosition;
canMove = true;
}
#endregion
}
}
4.将此脚本挂载到拖拽物体组件上,设置如下图所示,切记加上Rigidbody2D组件,其他拖拽物体组件也是相同设置:
5.这样就基本实现了拖拽功能,若需完善,还需要自己在代码丰富,我就不在这啰嗦了。