유니티

[유니티] Pan Zoom을 Touch와 EventSystems 혼합하여 사용하기

HorseDragon 2024. 4. 7. 19:44

Pan Zoom 기능을 해서 이미지를 이동시키고, 확대/축소하려고 했음.

처음에는 Touch 2개를 이용해서 했었는데, EventSystem을 체크하면 한번에 여러 이미지를 움직이는데 서로 싱크가 안 맞는다.

EventSystem 사용을 하지 않으면 싱크가 잘 맞아서 움직이는데 참으로 이상한 현상임.

해결하기 위한 방법을 찾아보니, UnityEngine.EventSystems에서 IDragHandler를 사용해서 Pan 기능을 이용하면 EventSystem과 충돌하지 않고 잘 움직일 것으로 보였음.

image라는 tag가 있는 녀석들을 찾고, 그 오브젝트가 동시에 움직일 수 있도록 구현을 해두었다.
public class PanZoom : MonoBehaviour, IPointerDownHandler, IDragHandler 
{
    Vector3 touchStart;
    public float zoomOutMin = 1;
    public float zoomOutMax = 8;
    public float dragSpeed = 1;
   
    // Update is called once per frame
    void Update () {
        if(Input.GetMouseButtonDown(0)){
            touchStart = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
        if(Input.touchCount == 2){
            Touch touchZero = Input.GetTouch(0);
            Touch touchOne = Input.GetTouch(1);
 
            Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
            Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
 
            float prevMagnitude = (touchZeroPrevPos - touchOnePrevPos).magnitude;
            float currentMagnitude = (touchZero.position - touchOne.position).magnitude;
 
            float difference = currentMagnitude - prevMagnitude;
 
            zoom(difference * 0.01f);
        }
        
        /* 이동하는 것은 EventSystem이용
        else if(Input.GetMouseButton(0)){
            Vector3 direction = touchStart - Camera.main.ScreenToWorldPoint(Input.mousePosition);
            gameObject.transform.position -= direction;
        }
        */
        zoom(Input.GetAxis("Mouse ScrollWheel"));
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        touchStart = Camera.main.ScreenToWorldPoint(eventData.position);
        touchStart.z = 0; // Z 축 값은 변화하지 않도록 고정
    }

    public void OnDrag(PointerEventData eventData)
    {      
        
        GameObject[] objectsToDrag = GameObject.FindGameObjectsWithTag("image");

        // 찾은 모든 객체를 이동시킴
        foreach (GameObject obj in objectsToDrag)
        {            
            Vector3 direction = touchStart - Camera.main.ScreenToWorldPoint(eventData.position);
            direction.z = 0; // Z 축 이동 방지
            // 방향을 반대로 해주어 이미지 이동 방향을 사용자의 드래그 방향과 일치시킴
            obj.transform.position -= direction*dragSpeed;
        }    
    }
 
    void zoom(float increment){
        float factor = Mathf.Clamp(gameObject.transform.localScale.x + increment, zoomOutMin, zoomOutMax);
        gameObject.transform.localScale = new Vector3(factor, factor, 0);
    }
}