使图像可在两个可滚动对象之间拖动
Make image draggable between two scrollables
我有两个不同的面板:
这是树:
在这些面板中,我希望用户能够点击左侧的图像,并在右侧拖动它们。
您可以找到大量 Unity "basic" UI 拖放教程,但它们的作用都是一样的:您可以在同一面板中的元素之间进行拖放。
我的问题是它们位于不同的面板中,因此我无法轻松地从一个面板拖放到另一个面板。
现在 我只是想让拖动原理在 PanelBoatsToDrag
中起作用:能够点击 Image
,并且可以将它 拖到 中 PanelBoatsToDrag
.
每个 Image
都是由预制件制成的。我已经向该预制件添加了一个 DragHandler.cs
脚本文件,它应该可以处理。这是:
public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public static GameObject itemBeingDragged;
private Vector3 startPosition;
public void OnBeginDrag(PointerEventData eventData)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
Debug.Log("OnBeginDrag\n" +
"eventData = " + eventData +
"\nInput.mousePosition = " + Input.mousePosition +
"\nCamera.main.ScreenToWorldPoint(Input.mousePosition) = " +
Camera.main.ScreenToWorldPoint(Input.mousePosition));
}
public void OnDrag(PointerEventData eventData)
{
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
itemBeingDragged = null;
transform.position = startPosition;
Debug.Log("OnEndDrag");
}
}
OnDrag(PointerEventData eventData)
代码根本不起作用。我需要将鼠标坐标转换为被单击的 Image
的本地坐标并将其分配给图像。如何实现?
Unity 还支持一种方法OnDrop()
。如果我是你,我会那样处理。在开始拖动 OnBeginDrag()
时,您应该做两件事:通过将对象的父级设置为 PanelMiddle
将对象移到更高层次,这样它就会被绘制在其他所有对象之上,并且 this.GetComponent<CanvasGroup>().blocksRaycasts = false;
这样您就不会进行光线投射进去。
之后它应该很简单:
public void OnDrop(PointerEventData eventData)
{
GameObject dropedItem = eventData.pointerDrag.GetComponent<GameObject>();
if (isEmpty) // you have space for this object
{
dropedItem.transform.SetParent(this.transform);
dropedItem.transform.position = //set to any position you need
dropedItem.GetComponent<CanvasGroup>().blocksRaycasts = true; //so you can pick this item again
}
else
{
//return it to old position and to old parent
}
}
方法 OnDrop()
应附加到面板或您要将项目拖到其中的某种插槽。
这是我的做法,我把 class 中唯一重要的部分放在这里:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour,
IBeginDragHandler, IDragHandler, IEndDragHandler
{
public void OnDrag(PointerEventData eventData)
{
CanvasScaler scaler = GetComponentInParent<CanvasScaler>();
Vector3 i_scale = itemBeingDragged.transform.localScale;
RectTransform rt = itemBeingDragged.GetComponent<RectTransform>();
Rect r = rt.rect;
/**
* Explanation: to center the object we need its width+height:
* Resize width to the current scale = r.width * i_scale.x
* Divide by 2 to get the center we have: (r.width * i_scale.x / 2)
* Same for y.
*
* Calculate the coords of the mouse proportional to the screen scale:
*/
rt.anchoredPosition = new Vector2(
(Input.mousePosition.x * scale_x) - (r.width * i_scale.x / 2),
(Input.mousePosition.y * scale_y) - (r.height * i_scale.y / 2));
// everybody tells me to apply this but it doesn't work:
// itemBeingDragged.GetComponent<CanvasGroup>().blocksRaycasts = true;
}
}
我有两个不同的面板:
这是树:
在这些面板中,我希望用户能够点击左侧的图像,并在右侧拖动它们。
您可以找到大量 Unity "basic" UI 拖放教程,但它们的作用都是一样的:您可以在同一面板中的元素之间进行拖放。
我的问题是它们位于不同的面板中,因此我无法轻松地从一个面板拖放到另一个面板。
现在 我只是想让拖动原理在 PanelBoatsToDrag
中起作用:能够点击 Image
,并且可以将它 拖到 中 PanelBoatsToDrag
.
每个 Image
都是由预制件制成的。我已经向该预制件添加了一个 DragHandler.cs
脚本文件,它应该可以处理。这是:
public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public static GameObject itemBeingDragged;
private Vector3 startPosition;
public void OnBeginDrag(PointerEventData eventData)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
Debug.Log("OnBeginDrag\n" +
"eventData = " + eventData +
"\nInput.mousePosition = " + Input.mousePosition +
"\nCamera.main.ScreenToWorldPoint(Input.mousePosition) = " +
Camera.main.ScreenToWorldPoint(Input.mousePosition));
}
public void OnDrag(PointerEventData eventData)
{
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
itemBeingDragged = null;
transform.position = startPosition;
Debug.Log("OnEndDrag");
}
}
OnDrag(PointerEventData eventData)
代码根本不起作用。我需要将鼠标坐标转换为被单击的 Image
的本地坐标并将其分配给图像。如何实现?
Unity 还支持一种方法OnDrop()
。如果我是你,我会那样处理。在开始拖动 OnBeginDrag()
时,您应该做两件事:通过将对象的父级设置为 PanelMiddle
将对象移到更高层次,这样它就会被绘制在其他所有对象之上,并且 this.GetComponent<CanvasGroup>().blocksRaycasts = false;
这样您就不会进行光线投射进去。
之后它应该很简单:
public void OnDrop(PointerEventData eventData)
{
GameObject dropedItem = eventData.pointerDrag.GetComponent<GameObject>();
if (isEmpty) // you have space for this object
{
dropedItem.transform.SetParent(this.transform);
dropedItem.transform.position = //set to any position you need
dropedItem.GetComponent<CanvasGroup>().blocksRaycasts = true; //so you can pick this item again
}
else
{
//return it to old position and to old parent
}
}
方法 OnDrop()
应附加到面板或您要将项目拖到其中的某种插槽。
这是我的做法,我把 class 中唯一重要的部分放在这里:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour,
IBeginDragHandler, IDragHandler, IEndDragHandler
{
public void OnDrag(PointerEventData eventData)
{
CanvasScaler scaler = GetComponentInParent<CanvasScaler>();
Vector3 i_scale = itemBeingDragged.transform.localScale;
RectTransform rt = itemBeingDragged.GetComponent<RectTransform>();
Rect r = rt.rect;
/**
* Explanation: to center the object we need its width+height:
* Resize width to the current scale = r.width * i_scale.x
* Divide by 2 to get the center we have: (r.width * i_scale.x / 2)
* Same for y.
*
* Calculate the coords of the mouse proportional to the screen scale:
*/
rt.anchoredPosition = new Vector2(
(Input.mousePosition.x * scale_x) - (r.width * i_scale.x / 2),
(Input.mousePosition.y * scale_y) - (r.height * i_scale.y / 2));
// everybody tells me to apply this but it doesn't work:
// itemBeingDragged.GetComponent<CanvasGroup>().blocksRaycasts = true;
}
}