-
Unity 3D Object Drag & DropUnity 2024. 6. 4. 09:00
Unity에서 3D 게임을 만들다 보면 3D GameObject를 컴퓨터의 경우 마우스, 모바일의 경우 손가락으로 자유롭게 Drag & Drop 하여 원하는 위치에 놓는 기능이 필요할때가 있다
위에서 서술한 기능을 나는 아래와 같이 구현하였다
https://www.youtube.com/shorts/H-rxX2ozjUE
우선 클릭 또는 터치 했을때 내가 Drag & Drop 하고자 하는 GameObject인지 구분부터 해야한다.
private GameObject OnClickObjUsingTag(string tag) { Vector3 touchPos = new Vector3(0, 0, 0); #if UNITY_EDITOR touchPos = Input.mousePosition; #else touchPos = Input.GetTouch(0).position; #endif Ray ray = Camera.main.ScreenPointToRay(touchPos); RaycastHit hitInfo; Physics.Raycast(ray, out hitInfo); if (hitInfo.collider != null) { GameObject hitObject = hitInfo.collider.gameObject; if (hitObject != null) { if (hitObject.gameObject.tag.Equals(tag)) { return hitObject; } } } return null; }
내가 터치한 위치로부터 Camera.main.ScreenPointToRay 함수를 사용해 Ray를 발사하여 Ray에 맞은 GameObject가 내가 이동시키고자 하는 GameObject인지 확인한다.
private void TouchMovedEvent() { if (_movableObj != null) { Vector3 touchPos = Vector3.zero; #if UNITY_EDITOR touchPos = Input.mousePosition; #else touchPos = Input.GetTouch(0).position; #endif Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(touchPos.x, touchPos.y, 10)); //_movableObj.transform.position = worldPos; _movableObj.transform.position = Vector3.MoveTowards(_movableObj.transform.position, worldPos, Time.deltaTime * 20f); } }
내가 이동시키려고 한 GameObject가 맞다면 내가 드래그 하는 동안 해당 GameObject를 내가 터치한 위치를 World Position으로 변환시킨(Camera.main.ScreenToWorldPoint 함수) 좌표값으로 이동시킨다
private void TouchEndedEvent() { if (_movableObj != null) { Ray ray = new Ray(_movableObj.transform.position, Camera.main.transform.forward); RaycastHit hitInfo; Physics.Raycast(ray, out hitInfo); if (hitInfo.collider != null) { Debug.Log("hit info : " + hitInfo.collider.gameObject.name); _movableObj.transform.position = hitInfo.collider.gameObject.transform.position; _movableObj.transform.position += _offset; } else { _movableObj.transform.position = _beforePosition; } } }
손가락을 땠을때는 Drag 되고 있든 GameObject로부터 Camera z 방향(forward)으로 Ray를 발사하여 그 Ray에 닿은 위치로 해당 게임오브젝트를 이동시킨다
전체코드
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace UnityStudy.DragDrop { public class TouchManager : MonoBehaviour { private Vector2 _lastTouchPos = Vector2.zero; private Vector2 _currentTouchPos = Vector2.zero; private Vector3 _prePos = Vector3.zero; private Vector3 _beforePosition; private Vector3 _offset = new Vector3(0.0f, 1.0f, 0.0f); [SerializeField] private GameObject _movableObj; private const string _moveableTAG = "Moveable"; private void Update() { #if UNITY_EDITOR _lastTouchPos = _currentTouchPos; _currentTouchPos = Input.mousePosition; if (Input.GetMouseButtonDown(0)) { TouchBeganEvent(); _prePos = Input.mousePosition; } if (Input.GetMouseButton(0)) { if (Input.mousePosition != _prePos) { TouchMovedEvent(); } else { TouchStayEvent(); } } if (Input.GetMouseButtonUp(0)) { TouchEndedEvent(); } #else // Multi-touch 방지 if (Input.touchCount <= 0) { return; } Touch touchInfo = Input.GetTouch(0); _lastTouchPos = _currentTouchPos; _currentTouchPos = touchInfo.position; switch (touchInfo.phase) { case TouchPhase.Began: TouchBeganEvent(); break; case TouchPhase.Moved: TouchMovedEvent(); break; case TouchPhase.Stationary: TouchStayEvent(); break; case TouchPhase.Ended: TouchEndedEvent(); break; } #endif #if UNITY_EDITOR // 캐릭터 Ray 확인용 if (_movableObj != null) { Ray ray = new Ray(_movableObj.transform.position, Camera.main.transform.forward); Debug.DrawRay(ray.origin, ray.direction * 1000, Color.red); } // TEST Code Vector3 touchPos = new Vector3(0, 0, 0); #if UNITY_EDITOR touchPos = Input.mousePosition; #else touchPos = Input.GetTouch(0).position; #endif Ray test_ray = Camera.main.ScreenPointToRay(touchPos); Debug.DrawRay(test_ray.origin, test_ray.direction * 1000, Color.blue); #endif } private void TouchBeganEvent() { _movableObj = OnClickObjUsingTag(_moveableTAG); if (_movableObj != null) { _beforePosition = _movableObj.transform.position; } } private void TouchMovedEvent() { if (_movableObj != null) { Vector3 touchPos = Vector3.zero; #if UNITY_EDITOR touchPos = Input.mousePosition; #else touchPos = Input.GetTouch(0).position; #endif Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(touchPos.x, touchPos.y, 10)); //_movableObj.transform.position = worldPos; _movableObj.transform.position = Vector3.MoveTowards(_movableObj.transform.position, worldPos, Time.deltaTime * 20f); } } private void TouchStayEvent() { } private void TouchEndedEvent() { if (_movableObj != null) { Ray ray = new Ray(_movableObj.transform.position, Camera.main.transform.forward); RaycastHit hitInfo; Physics.Raycast(ray, out hitInfo); if (hitInfo.collider != null) { Debug.Log("hit info : " + hitInfo.collider.gameObject.name); _movableObj.transform.position = hitInfo.collider.gameObject.transform.position; _movableObj.transform.position += _offset; } else { _movableObj.transform.position = _beforePosition; } } //_movableObj = null; } private GameObject OnClickObjUsingTag(string tag) { Vector3 touchPos = new Vector3(0, 0, 0); #if UNITY_EDITOR touchPos = Input.mousePosition; #else touchPos = Input.GetTouch(0).position; #endif Ray ray = Camera.main.ScreenPointToRay(touchPos); RaycastHit hitInfo; Physics.Raycast(ray, out hitInfo); if (hitInfo.collider != null) { GameObject hitObject = hitInfo.collider.gameObject; if (hitObject != null) { if (hitObject.gameObject.tag.Equals(tag)) { return hitObject; } } } return null; } } }
'Unity' 카테고리의 다른 글
Unity Design Pattern - Object Pool (2) 2024.06.03 유니티 3D Model 파괴 효과 만들기 (0) 2024.02.26 Unity Android Plugin 만들기 (2) 2024.01.28 Mac에서의 classes.jar 위치 (0) 2021.10.31 [Unity] Animator Animation 재시작 방법 (0) 2021.10.29