对象拖动不以与指针相同的速率移动

时间:2015-08-12 14:04:20

标签: c# unity3d drag-and-drop

我正在尝试实施拖放系统,但此刻我的拖动率有问题。目前,当我拖动一个物体时,它只移动我的指针实际移动量的一小部分。我该如何解决这个问题?

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;

public class DragHandling : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
{
    public float partScale;

    [HideInInspector] public Transform placeholderParent = null;
    [HideInInspector] public Transform parentToReturnTo = null;
    [HideInInspector] public GameObject trashCan; 
    [HideInInspector] public GameObject partsPanel;
    [HideInInspector] public GameObject partsWindow;
    [HideInInspector] public GameObject buildBoard;

    GameObject placeholder = null;
    GameObject dragLayer;
    Vector3 buildPanelScale;
    Vector3 partsPanelScale = new Vector3(1.0f, 1.0f, 1.0f);
    Vector3 startPosition;

    private Vector3 offset = Vector3.zero;

    void Start ()
    {
        dragLayer = GameObject.FindGameObjectWithTag("DragLayer");
        buildBoard = GameObject.FindGameObjectWithTag("Board");
        partsPanel = GameObject.FindGameObjectWithTag("Parts");
        partsWindow = GameObject.FindGameObjectWithTag("PartsWindow");
        trashCan = GameObject.FindGameObjectWithTag("Trash");
    }

    #region IPointerClickHandler implementation

    public void OnPointerClick (PointerEventData eventData)
    {
        if(transform.parent.gameObject == buildBoard)
            transform.SetAsLastSibling();
    }

    #endregion

    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        worldPos.z = transform.position.z;
        offset = worldPos - transform.position;

        // create placeholder gap and hold correct position in layout
        placeholder = new GameObject();
        placeholder.transform.SetParent(transform.parent);
        placeholder.transform.SetSiblingIndex(transform.GetSiblingIndex());
        parentToReturnTo = transform.parent;                                    // store original parent location
        placeholderParent = parentToReturnTo;                                   // set placeholder gameobject transform
        GetComponent<CanvasGroup>().blocksRaycasts = false;                     // turn off image raycasting when dragging image in order to see what's behind the image            
    }

    #endregion

    #region IDragHandler implementation

    public void OnDrag (PointerEventData eventData)
    {
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        worldPos.z = transform.position.z;
        worldPos = worldPos - offset;
        transform.position = worldPos;

        if(transform.parent.gameObject == partsPanel)
            transform.SetParent(dragLayer.transform);                                       // pop object to draglayer to move object out of parts Panel
        if(transform.parent.gameObject == buildBoard)
            transform.SetParent(dragLayer.transform);
    }

    #endregion

    #region IEndDragHandler implementation

    public void OnEndDrag (PointerEventData eventData)
    {
        offset = Vector3.zero;

        transform.SetParent(parentToReturnTo);                                  // Snaps object back to orginal parent if dropped outside of a dropzone
        transform.SetSiblingIndex(placeholder.transform.GetSiblingIndex());     // Returns card back to placeholder location
        GetComponent<CanvasGroup>().blocksRaycasts = true;                      // turn Raycast back on
        Destroy(placeholder);                                                   // kill the placeholder if object hits a drop zone or returns to parts panel

        if(transform.parent.gameObject == buildBoard)
        {
            buildPanelScale = new Vector3(partScale, partScale, partScale);
            transform.localScale = buildPanelScale;
            transform.SetAsLastSibling();                                       // always place last piece on top
        }
        if(transform.parent.gameObject == partsPanel)
            transform.localScale = partsPanelScale;
    }

    #endregion

}

1 个答案:

答案 0 :(得分:1)

从背面开始,您应该使用eventData.position代替Input.mousePositionScreenToWorldPoint需要Vector3Input.mousePositionVector2。我个人也不会为此目的使用ScreenToWorldPoint,id使用光线投射,并使用RayCastHit hit.point将对象放在哪里放置,这对你来说会更准确。 / p>

实际上,由于您使用的是Unity Canvas,因此您应该使用RectTransformUtility.ScreenPointToLocalPointInRectangle(...)并在父级rect或画布中放置您要拖动的内容。它会为您提供所需的坐标。

实现:

RectTransform parentRect = (RectTransform)objectToBeDragged.transform.parent;
Vector2 posInParent;
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRect, eventData.position, Camera.main, out posInParent);

objectToBeDragged.localPosition = posInParent;

我也刚刚意识到您可能遇到的另一个问题是您使用的是transform.position而不是transform.localPosition没有确定问题,但有时可能真的会让您陷入困境。