greyBow
greyBow

Reputation: 1348

Prevent object from jumping to center point when dragging starts

I have a script for dragging GameObjects around, but at the moment, whenever I start to drag on the object it jumps to the center itself onto the pointer. What I'd like to achieve is regardless of where I start to drag on the object it initiates drag at that point instead of jumping to the object center first. What do I need to modify in my OnDrag or OnBeginDrag method to achieve this?

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;

    // PolygonCollider2D collider;

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

        // collider = transform.GetComponent<PolygonCollider2D>();
    }

    #region IPointerClickHandler implementation

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

    #endregion

    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {
        // 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
        startPosition = transform.position;
        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 mousePosition = new Vector3(eventData.position.x, eventData.position.y, 0);
        transform.position = Input.mousePosition;                                           // set object coordinates to mouse coordinates

        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)
    {
        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

}

Upvotes: 1

Views: 1646

Answers (2)

Vinod Vijayan
Vinod Vijayan

Reputation: 108

I have never used any interface to implement this, But the solution should be the same as using with OnMouseDown, OnMouseUp and OnMouseDrag with the sprites. Try this with your current implementation

 using UnityEngine;
using System.Collections;

public class Drag : MonoBehaviour {

    private Vector3 offset = Vector3.zero;

    void OnMouseDown () {
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        worldPos.z = transform.position.z;
        offset = worldPos - transform.position;
    }


    void OnMouseDrag () {
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        worldPos.z = transform.position.z;
        worldPos = worldPos - offset;
        transform.position = worldPos;
    }


    void OnMouseUp () {
        offset = Vector3.zero;
    }

}

I have used this with an orthographic camera on Sprites. Hope this helps.

EDIT

Tried implementing the interfaces as in your code with UI elements. It is working as expected. Only thing is to set the canvas to ScreenSpace-Camera implement the code in the respective interfaces

Upvotes: 4

LumbusterTick
LumbusterTick

Reputation: 1075

your question is a bit confusing and if im correct you are saying that the object you start to drag keeps moving to the middle of screen , if you dont want that just update the dragged objects transform in OnEndDrag.

Upvotes: 0

Related Questions