[Unity][개발#1]Drag & Drop, 블록코딩, 드래그, 드랍

2021. 4. 29. 10:55PROJECT/VR 소프트웨어 코딩교육 플랫폼

Unity 블록코딩 구현을 위한 Drag & Drop 이다

블록코딩을 하게 될 캔버스

 

영역은 3가지로 왼쪽부터 미니맵, 블록, 블록이 쌓이는 공간으로 나뉜다.

대략적인 구상이며 가운데공간의 버튼 4가지는 각각 단일동작 블록, 반복문, 함수생성, 함수저장으로 사용될 예정이다.

오른쪽에 블록들이 차곡차곡 쌓이기 위해 Content Size Fitter와 Vertical Layout Group을 넣어주었다.

 

Drag and Drop을 하기 위해서는 필요한 인터페이스가 존재한다.

IDragHandler = 드래그하는 동안, IEndDragHandler = 드래그 끝났을 때, IPointerDownHandler = 클릭할때

 

 public void OnDrag(PointerEventData eventData)
    {
        
        // 마우스 좌표 인식해서 블록 이동
        Vector3 obj = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 mouseposition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, obj.z);
        Vector3 objPosition = Camera.main.ScreenToWorldPoint(mouseposition);
        transform.position = objPosition;

    }

 

Camera.main.WorldToScreenPoint를 이용하여 월드좌표상의 마우스를 스크린좌표상으로 바꿔준다.

마우스에 오브젝트가 잘 붙어서 움직이는 것을 확인할 수 있다.

Camera.main.ScreenWorldToWorldPoint를 사용하여 다시 좌표를 월드 좌표로 바꿔준다.

 

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

public class UIDrop : MonoBehaviour, IDropHandler
{
    public void OnDrop(PointerEventData Data)
    {
        EventSystem.current.currentSelectedGameObject.transform.parent = transform;
        EventSystem.current.currentSelectedGameObject.transform.SetAsLastSibling();
        //LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent<RectTransform>());
    }
}

 

이제 잘 움직이는 오브젝트를 Drop해야한다 나는 Drag 와 Drop을 별개의 스크립트로 사용한다.

SetAsLastSibling은 자식오브젝트 중에 가장 하위로 붙는다는 의미이다.

 

여기서 나는 오브젝트가 움직일때 원래 위치에도 블록이 남아 있어야 계속해서 블록을 가져다 쓸 수 있다.

 public void OnEndDrag(PointerEventData eventData)
    {
        if (CloneBlock == null)
        {
            CloneBlock = Instantiate(gameObject, StartPos, transform.rotation) as GameObject; ///블록생성
            CloneBlock.transform.localScale = new Vector3(2.77f, 3, 1); ///scale값 변경
            CloneBlock.transform.SetParent(ParentPos); ///다시 원래 부모 오브젝트로 돌아감
            //GetComponent<Image>().raycastTarget = true;
        }
        Debug.Log("OnEndDrag");
    }

 

CloneBlock이 널값인걸로 판단하여 클론을 생성한다.

 


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

public class UIDrag : MonoBehaviour,  IDragHandler, IPointerDownHandler, IEndDragHandler
{
    GameObject canvas_;
    Transform ParentPos;
    Vector3 StartPos;
    GameObject CloneBlock;
    void Start()
    {
        ParentPos = transform.parent; ///부모 트랜스폼 저장
        StartPos = transform.position; ///처음위치
        canvas_ = GameObject.Find("Panel");
    }

    public void OnDrag(PointerEventData eventData)
    {
        // 마우스 좌표 인식해서 블록 이동
        Vector3 obj = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 mouseposition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, obj.z);
        Vector3 objPosition = Camera.main.ScreenToWorldPoint(mouseposition);
        transform.position = objPosition;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (CloneBlock == null)
        {
            CloneBlock = Instantiate(gameObject, StartPos, transform.rotation) as GameObject; ///블록생성
            CloneBlock.transform.localScale = new Vector3(2.77f, 3, 1); ///scale값 변경
            CloneBlock.transform.SetParent(ParentPos); ///다시 원래 부모 오브젝트로 돌아감
            //GetComponent<Image>().raycastTarget = true;
        }
        Debug.Log("OnEndDrag");
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        EventSystem.current.SetSelectedGameObject(gameObject);
        EventSystem.current.currentSelectedGameObject.transform.SetParent(canvas_.transform);
        EventSystem.current.currentSelectedGameObject.transform.SetSiblingIndex(2);
        //Debug.Log("start drag " + gameObject.name);
        Debug.Log("OnPointerDown");
    }
}