主要思想: 我在canvas 模拟一个点,并从这个点发射射线,这个模拟点根据鼠标的位置进行移动,射线检测到UI并返回一个List,我从这个List中获取 想要的物体。
既然我们已经拿到了物体,其它的就是一些基本的逻辑处理。
测试demo:
注意
我添加三个标签:
empty 判断格子是空的
image 图片交换的标签
bg 图片背景的标签(可以不要)
(这种写法,把不需要UI交互的,要把UI的射线关了)
image.png
我给需要交互的UI添加CanvasGroup,目的是为了检测UI叠加时,检测下面一个物体。
鼠标按下
当我鼠标按下,会发射一次射线,获取我鼠标当前的物体的tag,判断是否可以拖动,如果可以拖动并记录位置信息,并关闭CanvasGroup的blocksRaycasts。记录位置信息目的是当天图片与另一张图片替换时,另一张图片需要移动的位置。blocksRaycasts=false的目的是,穿透鼠标当前有图片,检测下面的图片
鼠标拖动
直接把鼠标的位置赋值给UI就ok了。
鼠标抬起
当我鼠标抬起,会发射一次射线,获取我鼠标当前的物体的tag,判断是否可以放下,替换,返回开始位置,并把拖动图片的blocksRaycasts开启(防止穿透)
效果图
image.gif public EventSystem eventSystem;
public StandaloneInputModule standaloneInputModule;
public GameObject canvas;
private PointerEventData pointerEventData;
private GraphicRaycaster gr;
private CanvasGroup itemCanvasGroup;
private Transform currntGameObject; //当前拖动的物体
private Transform swpObj; //交换的物体
private string targetTag = "empty"; //判断格子是空的
private string swapTag = "image"; //图片交换的标签
private string bgTag = "bg"; //图片背景的标签
private Vector3 startPos; //鼠标之前的位置
private Vector3 endPos; //结束的位置
private bool Stop = false;
private List<RaycastResult> mousMoveResults = new List<RaycastResult>();
private void Start()
{
gr = canvas.GetComponent<GraphicRaycaster>();
}
private void Update()
{
GetOverUI();
}
/// <summary>
/// 获取鼠标停留处UI
/// </summary>
/// <returns></returns>
public void GetOverUI()
{
if (Input.GetMouseButtonDown(0))
{
GetTransform(out currntGameObject, out startPos);
if (currntGameObject != null&& currntGameObject.tag.Contains(swapTag))
{
currntGameObject.transform.SetAsLastSibling();
Stop = false;
}
else
{
Stop = true;
}
}
if (!Stop)
{
if (Input.GetMouseButton(0))
{
ContinuedMouseButtonDowm();
}
if (Input.GetMouseButtonUp(0))
{
SwpObjPos();
if (itemCanvasGroup != null)
itemCanvasGroup.blocksRaycasts = true;
}
}
}
/// <summary>
/// 持续鼠标按下
/// </summary>
private void ContinuedMouseButtonDowm()
{
if (itemCanvasGroup == null || itemCanvasGroup.blocksRaycasts)
{
itemCanvasGroup = currntGameObject.GetComponent<CanvasGroup>();
itemCanvasGroup.blocksRaycasts = false;
}
currntGameObject.transform.position = Input.mousePosition;
}
/// <summary>
/// 交换物体的位置
/// </summary>
private void SwpObjPos()
{
GetTransform(out swpObj, out endPos);
if (swpObj == null)
{
currntGameObject.position = startPos;
}
else if (swpObj.tag.Contains(targetTag))
{
currntGameObject.position = swpObj.position;
}
else if (swpObj.tag.Contains(swapTag))
{
swpObj.position = startPos;
currntGameObject.position = endPos;
}
else
{
currntGameObject.position = startPos;
}
}
/// <summary>
/// 获取对象
/// </summary>
/// <param name="getTra">返回获取的物体</param>
/// <param name="record">记录鼠标当前的坐标</param>
private void GetTransform(out Transform getTra, out Vector3 record)
{
mousMoveResults.Clear();
if (pointerEventData == null)
pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = Input.mousePosition;
gr.Raycast(pointerEventData, mousMoveResults);
if (mousMoveResults.Count != 0)
{
getTra = mousMoveResults[0].gameObject.transform;
record = getTra.position;
}
else
{
getTra = null;
record = Vector3.zero;
}
}
/// <summary>
/// 清空mousMoveResults
/// </summary>
private void ClearMousMoveResultsList()
{
mousMoveResults.Clear();
}
网友评论