드래그로 오브젝트 Y축 회전하기 (Drag to Rotate Object in Y-axis)
드래그로 오브젝트 위, 아래로 움직이기 (Drag Object in Y-Axis)
드래그로 오브젝트 움직이기 (Move GameObject with Drag)
드래그로 땅 위의 오브젝트 움직이기 (Drag and Move on the Ground)
드래그로 평면 위의 오브젝트 움직이기 (Drag and Move on the Plane)
드래그로 블럭 옆으로 한 칸 움직이기 (Drag GameObject Snapped to a Grid)
아래와 같이 드래그로 블럭을 움직이고, 한 칸 단위(그리드)로만 움직이도록 구현해보자.
먼저 드래그로 자연스럽게 블럭을 움직이기 위해서는 블럭의 뒤에 Plane이 숨겨져있어야 한다.
관련 내용은 링크를 참고하자.
여기에서는 블럭이 평면에 붙지 않고 현재 위치를 그대로 움직이므로 OnMouseDrag가 아래와 같이 변경된다.
planeDot이 현재 hitPos의 position이면 현재 상태(Plane과 큐브와의 거리)를 유지하게 된다.
그리고 x 축(오른쪽과 왼쪽)으로만 움직이도록 position을 수정한다.
void OnMouseDrag()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
int layer = 1 << LayerMask.NameToLayer(HIDDEN_PLANE);
if (Physics.Raycast(ray, out hitLayerMask, Mathf.Infinity, layer))
{
Vector3 normal = hitLayerMask.transform.up;
Vector3 planeDot = hitPos.transform.position;
Vector3 A = Camera.main.transform.position;
Vector3 B = hitLayerMask.point;
Vector3 temp = getContactPoint(normal, planeDot, A, B);
Vector3 setPos = hitPos.transform.position;
setPos.x = temp.x;
hitPos.transform.position = setPos;
}
}
숨겨진 평면의 Layer는 HiddenPlane이다. 코드에서 const로 정의해둔다.
int layer = 1 << LayerMask.NameToLayer(HIDDEN_PLANE);
이제 코루틴으로 한 칸 단위로만 움직이도록 하면 된다.
어디로 움직여야할지 moveBlock에 알려주면 blockMoveTime 동안 그 자리로 이동한다.
public void moveBlock(Vector3 targetPosition)
{
StartCoroutine(moveBlockCoroutine(targetPosition));
}
private IEnumerator moveBlockCoroutine(Vector3 targetPosition)
{
float elapsedTime = 0.0f;
Vector3 currentPosition = transform.position;
while (elapsedTime < blockMoveTime)
{
elapsedTime += Time.deltaTime;
transform.position = Vector3.Lerp(currentPosition, targetPosition, elapsedTime / blockMoveTime);
yield return null;
}
transform.position = targetPosition;
}
마우스를 뗐을 때, 호출해주면 된다.
돌아가야할 위치는 현재 위치에서 반올림한 위치로 돌아가도록 하였다.
void OnMouseUp()
{
this.transform.parent = null;
Destroy(hitPos);
Vector3 tempPos = this.transform.position;
tempPos.x = Mathf.Round(tempPos.x);
moveBlock(tempPos);
}
아래의 코드를 블럭에 추가하고 블럭이 콜라이더를 가지고 있으면 정상 작동한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Block : MonoBehaviour
{
const string HIDDEN_PLANE = "HiddenPlane";
public float blockMoveTime = .3f;
RaycastHit hit, hitLayerMask;
GameObject hitPos;
Vector3 getContactPoint(Vector3 normal, Vector3 planeDot, Vector3 A, Vector3 B)
{
Vector3 nAB = (B - A).normalized;
return A + nAB * Vector3.Dot(normal, planeDot - A) / Vector3.Dot(normal, nAB);
}
void OnMouseDown()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
hitPos = new GameObject("Empty");
hitPos.transform.position = hit.point;
this.transform.SetParent(hitPos.transform);
}
}
void OnMouseDrag()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
int layer = 1 << LayerMask.NameToLayer(HIDDEN_PLANE);
if (Physics.Raycast(ray, out hitLayerMask, Mathf.Infinity, layer))
{
Vector3 normal = hitLayerMask.transform.up;
Vector3 planeDot = hitPos.transform.position;
Vector3 A = Camera.main.transform.position;
Vector3 B = hitLayerMask.point;
Vector3 temp = getContactPoint(normal, planeDot, A, B);
Vector3 setPos = hitPos.transform.position;
setPos.x = temp.x;
hitPos.transform.position = setPos;
}
}
void OnMouseUp()
{
this.transform.parent = null;
Destroy(hitPos);
Vector3 tempPos = this.transform.position;
tempPos.x = Mathf.Round(tempPos.x);
moveBlock(tempPos);
}
public void moveBlock(Vector3 targetPosition)
{
StartCoroutine(moveBlockCoroutine(targetPosition));
}
private IEnumerator moveBlockCoroutine(Vector3 targetPosition)
{
float elapsedTime = 0.0f;
Vector3 currentPosition = transform.position;
while (elapsedTime < blockMoveTime)
{
elapsedTime += Time.deltaTime;
transform.position = Vector3.Lerp(currentPosition, targetPosition, elapsedTime / blockMoveTime);
yield return null;
}
transform.position = targetPosition;
}
}
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
'개발 > Unity' 카테고리의 다른 글
유니티 쉐이더 - 카메라가 바라보는 방향으로 밝아지는 큐브 (0) | 2022.06.14 |
---|---|
유니티 - BoundBox로 블럭이 움직일 위치 미리 예상하기 (Runtime Collider, 런타임 콜라이더) (0) | 2022.06.12 |
유니티 쉐이더 - 카메라 흑백 효과로 게임 오버 이펙트 만들기 (Camera Game Over Effect) (0) | 2022.06.11 |
유니티 - 전처리기 지시문을 사용하여 조건부 컴파일하기 (Scripting Define Symbols) (0) | 2022.06.10 |
유니티 - 스크립트로 게임 일시정지하기 (Unity Pause by Scirpt) (0) | 2022.06.10 |
댓글