在 2 个游戏对象之间拖放

Drag and Drop between 2 gameObjects

我的场景中有 2 个球体。我希望能够将我的鼠标从一个球体拖放到另一个球体,并在拖动时有一个指示器(例如一条直线)。释放鼠标按钮后,我想在第一个球体中存储另一个球体(作为 GameObject)。

我在UnityScript中需要这个,但我可以接受C#的想法。

到目前为止,我已经考虑过第一个 Sphere 上的 onMouseDown 事件,然后 onMouseEnter 到另一个 sphere,我会将数据存储在一些全局变量中(我不知道如何做)并且在 onMouseExit 的情况下,我将把全局变量设为 null。

然后 onMouseUp 在第一个球体上,我会将全局变量存储在按下的对象(球体)中。

关于如何操作的任何提示和技巧?

Assumptions/Setup

  1. 您正在 2D 世界空间中工作;这部分解决方案的拖动对象逻辑需要更改。

  2. 点击拖动后设置父级,指的是将未点击的对象设置为点击的父级的子级。

  3. 相机应该是正交相机;使用透视相机会导致拖动与您认为应该的位置不对齐。

  4. 为了使拖动工作,我创建了一个用作 'background' 到 2D 场景的四边形,并将其放在一个名为 'background' 的新图层上.然后设置layermask字段只使用背景层。

  5. 为线条渲染器创建并设置一个 material,(我在上面的示例中使用 Particles/Additive 着色器), 以及我使用 Start Width: 0.75, End Width: 0 的线条渲染器的参数,并确保勾选 Use World Space

说明

首先将 otherSphere 字段设置为指向场景中的另一个球体。 OnMouseDownOnMouseUp 切换 mouseDown 布尔值,用于确定是否应更新线渲染器。这些也用于转动 on/off 线渲染器和 set/remove 两个球体的父变换。

为了获得要拖动到的位置,我使用方法 ScreenPointToRay 根据鼠标在屏幕上的位置获得一条射线。如果你想为这个拖动功能添加平滑,你应该在底部启用 if (...) else 语句,并将 lerpTime 设置为一个值(0.25 对我来说效果很好)。

注意;当您释放鼠标时,父对象会立即设置,因此两个对象最终都会被拖动,但是子对象 return 无论如何都会回到原来的位置。

[RequireComponent(typeof(LineRenderer))]
public class ConnectedSphere : MonoBehaviour
{
    [SerializeField]
    private Transform       m_otherSphere;
    [SerializeField]
    private float           m_lerpTime;
    [SerializeField]
    private LayerMask       m_layerMask;

    private LineRenderer    m_lineRenderer;
    private bool            m_mouseDown;
    private Vector3         m_position;
    private RaycastHit      m_hit;

    public void Start()
    {
        m_lineRenderer          = GetComponent<LineRenderer>();
        m_lineRenderer.enabled  = false;
        m_position              = transform.position;
    }

    public void OnMouseDown()
    {
        //Un-parent objects
        transform.parent        = null;
        m_otherSphere.parent    = null;

        m_mouseDown             = true;
        m_lineRenderer.enabled  = true;
    }

    public void OnMouseUp()
    {
        //Parent other object
        m_otherSphere.parent    = transform;

        m_mouseDown             = false;
        m_lineRenderer.enabled  = false;
    }

    public void Update()
    {
        //Update line renderer and target position whilst mouse down
        if (m_mouseDown)
        {
            //Set line renderer
            m_lineRenderer.SetPosition(0, transform.position);
            m_lineRenderer.SetPosition(1, m_otherSphere.position);

            //Get mouse world position
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out m_hit, m_layerMask))
            {
                m_position.x    = m_hit.point.x;
                m_position.y    = m_hit.point.y;
            }
        }

        //Set position (2D world space)
        //if (m_lerpTime == 0f)
            transform.position = m_position;
        //else
            //transform.position = Vector3.Lerp(transform.position, m_position, Time.deltaTime / m_lerpTime);
    }
}

希望这对某人有所帮助。