我实现了一个实现IDragHandler的Unity组件,以及另一个实现IDropHandler的组件。 IDragHandler组件放在我想要拖动的对象上,但IDropHandler组件附加到我可以删除上的对象的对象,而不是我可以删除的对象。
我使用透视相机在3D中工作。
下面的代码可以很好地删除3D对象上的3D对象和2D UI对象上的3D对象,但不能用于删除3D对象上的2D UI对象或2D UI对象上的2D UI对象。
我遇到的问题是,由于EventSystem的Raycasting(即使我没有实现IDropHandler),我拖动的对象会阻止OnDrop并自行接收它。那个对象)。
对于3D对象,我在我的IDragHandler组件中拖动时暂时禁用了碰撞器,以确保决定哪个对象提供OnDrop的Raycast会被拖动的对象传递到其后面的对象。 但是,2D UI对象不能使用碰撞器进行拖放,因此没有可用于禁用的碰撞器。我不知道如何确保EventSystem Raycast绕过拖动的对象以将OnDrop传递给它后面的对象。
public void OnBeginDrag(PointerEventData eventData)
{
...
if (UIObject)
{
// What to do here?
}
else
{
var collider = gameObject.GetComponent<Collider>();
collider.enabled = false;
}
}
public void OnDrag(PointerEventData eventData)
{
// Move object and stuff
...
}
public void OnEndDrag(PointerEventData eventData)
{
if (UIObject)
{
// What to do here?
}
else
{
var collider = gameObject.GetComponent<Collider>();
collider.enabled = true;
}
}
到目前为止我尝试过的事情是:
1)暂时将gameObject放在IgnoreRaycast图层
中2)向对象添加画布组并暂时关闭&#34; Block Raycast&#34;在它上面。
我在OnBeginDrag中做的任何事情似乎都没有效果,直到我因某种原因实际丢弃了对象。尝试上面提到的#2导致它没有关闭&#34; Block Raycast&#34;直到物体掉落之后,这导致物体不再可以拖动。
答案 0 :(得分:1)
我做了一个解决方法,在OnEndDrag中使用拖动的对象进行光线投射,并查找它是否被放置在某个东西上,如果是,则在该对象上调用OnDrop。现在,3D对象上的对撞机的禁用和启用已经过时,因此已将其删除。
public void OnBeginDrag(PointerEventData eventData)
{
...
}
public void OnDrag(PointerEventData eventData)
{
// Move object and stuff
...
}
public void OnEndDrag(PointerEventData eventData)
{
// Currently using transform.position as raycast origin, could easily be something else if desired.
var rayCastOrigin = transform.position;
// Save the current layer the dropped object is in,
// and then temporarily place the object in the IgnoreRaycast layer to avoid hitting self with Raycast.
int oldLayer = gameObject.layer;
gameObject.layer = 2;
var raycastOriginInScreenSpace = Camera.main.WorldToScreenPoint(rayCastOrigin);
var screenRay = Camera.main.ScreenPointToRay(new Vector3(raycastOriginInScreenSpace.x, raycastOriginInScreenSpace.y, 0.0f));
// Perform Physics.Raycast from transform and see if any 3D object was under transform.position on drop.
RaycastHit hit3D;
if (Physics.Raycast(screenRay, out hit3D))
{
var dropComponent = hit3D.transform.gameObject.GetComponent<IDropHandler>();
if (dropComponent != null)
dropComponent.OnDrop(eventData);
}
// Perform Physics2D.GetRayIntersection from transform and see if any 2D object was under transform.position on drop.
RaycastHit2D hit2D = Physics2D.GetRayIntersection(screenRay);
if (hit2D)
{
var dropComponent = hit2D.transform.gameObject.GetComponent<IDropHandler>();
if (dropComponent != null)
dropComponent.OnDrop(eventData);
}
// Reset the object's layer to the layer it was in before the drop.
gameObject.layer = oldLayer;
}
我想要的行为是,当某个对象的transform.position被放置在某个东西上时,它被视为已丢弃。默认行为,当鼠标指针位于掉落的对象内时,它触发onDrop,可以通过交换轻松实现
var raycastOriginInScreenSpace = Camera.main.WorldToScreenPoint(rayCastOrigin);
var screenRay = Camera.main.ScreenPointToRay(new Vector3(raycastOriginInScreenSpace.x, raycastOriginInScreenSpace.y, 0.0f));
带
var screenRay = Camera.main.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, 0.0f));