2
\$\begingroup\$

I implemented my camera drag using the following method:

 if (Input.GetMouseButtonDown(0))
        {
            dragging = true;
            followPlayer = false;
            oldPos = transform.position;
            panOrigin = Camera.main.ScreenToViewportPoint(Input.mousePosition);
        }

        if (Input.GetMouseButton(0))
        {
            Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition) - panOrigin;
            transform.position = oldPos + -pos * panSpeed;
            transform.position = new Vector3(Mathf.Clamp(transform.position.x, xMin, xMax), Mathf.Clamp(transform.position.y, yMin, yMax), transform.position.z);
        }

        if (Input.GetMouseButtonUp(0))
        {
            dragging = false;
            //  followPlayer = true;
        }

But i also have draggable UI components that implement the IBeginDragHandler, IDragHandler, IEndDragHandler interfaces. Problem is of course while draging the item in the canvas the camera still moves. Any idea how to solve this besides the obvious setting of bools in the inplementation of the interfaces to prevent the camera drag code from executing. An other problem is that I have other non UI object in the game that I want to click so implementing a transparent UI element behind all other UI will not work for me.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Problem is of course while dragging the item in the canvas the camera still moves.

So If you want separate the two dragging operation , you should define conditions like this:

if(click on UI) Drag UI
if(click on Objects) Drag Camera 

enter image description here

I used EventSystem.IsPointerOverGameObject for detecting UI elements

Description

Is the pointer with the given ID over an EventSystem object? https://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.IsPointerOverGameObject.html

Attach this Script to your Camera:

using UnityEngine;
using UnityEngine.EventSystems;

public class CameraDragable : MonoBehaviour
{
    public float panSpeed = 20;
    public Vector2 XLimit = new Vector2(0,50), YLimit = new Vector2(0, 50); // xMin , xMin & yMin , yMin
    public Vector3 oldPos, panOrigin;
    public bool DragUI;


    void Update()
    {
        // Check if the mouse was clicked over a UI element
        if (EventSystem.current.IsPointerOverGameObject() && Input.GetMouseButtonDown(0))
        {
            Debug.Log("Clicked on the UI");
            DragUI = true;
        }

        if (Input.GetMouseButtonDown(0))
        {
                oldPos = transform.position;
                panOrigin = Camera.main.ScreenToViewportPoint(Input.mousePosition);
        }

        if (Input.GetMouseButton(0) && !DragUI)
        {
            Debug.Log("Clicked on the Object");
            Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition) - panOrigin;
            transform.position = oldPos - pos * panSpeed;
            transform.position = new Vector3(Mathf.Clamp(transform.position.x, XLimit.x, XLimit.y), Mathf.Clamp(transform.position.y, YLimit.x, YLimit.y), transform.position.z);
        }

        if (Input.GetMouseButtonUp(0))
        {
            DragUI = false;
        }
    }
}

Attach this Script to UI elements that should be draggrable:

using UnityEngine;
using UnityEngine.EventSystems;

public class UIDraggable : MonoBehaviour, IDragHandler
{
    public void OnDrag(PointerEventData eventData)
    {
        Debug.Log("OnDrag");

        this.transform.position = eventData.position;

    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Please edit the code to be cleaner. Also make it clear that what gets the job done is "EventSystem.current.IsPointerOverGameObject()". \$\endgroup\$ Jun 12, 2017 at 9:17
  • \$\begingroup\$ @S.TarıkÇetin Teşekkürler I edit my answer. \$\endgroup\$ Jun 12, 2017 at 18:10
0
\$\begingroup\$

The critical aspect is for touch screens you need to check like this:

if(Input.touchCount > 0)
{
    if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) return;
}

to stop camera control gestures

for non touch screens you simply check on mouse button down:

if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
{
    if(EventSystem.current.IsPointerOverGameObject()) return;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .