마우스 드래그 제어란?
마우스 드래그 제어는 사용자가 마우스를 클릭하고 드래그한 거리와 방향을 감지하여 오브젝트를 이동시키는 기능입니다. 게임에서 자동차를 스와이프로 제어하거나, 오브젝트를 드래그하여 이동시킬 때 사용합니다.
기본 개념
- 드래그 시작: 마우스 버튼을 누른 순간의 위치 저장
- 드래그 종료: 마우스 버튼을 뗀 순간의 위치 저장
- 드래그 거리: 시작 위치와 종료 위치의 차이 계산
- 속도 변환: 드래그 거리를 이동 속도로 변환
- 감속 효과: 속도를 점진적으로 줄여 자연스럽게 멈추는 효과
- 상태 관리: 플래그 변수(variable)로 드래그 상태와 드래그 가능 여부를 관리
Input.mousePosition
기본 사용법
using UnityEngine;
public class MousePosition : MonoBehaviour
{
void Update()
{
// 현재 마우스 위치 가져오기 (화면 좌표계)
Vector3 mousePos = Input.mousePosition;
// X, Y 좌표 출력
Debug.Log($"마우스 X: {mousePos.x}, Y: {mousePos.y}");
}
}
mousePosition 특징
- 화면 좌표계: 왼쪽 아래가 (0, 0), 오른쪽 위가 (Screen.width, Screen.height)
- 픽셀 단위: 화면 해상도에 따라 값이 달라짐
- 2D 좌표: Z 값은 항상 0 (카메라와의 거리)
화면 좌표 예시
using UnityEngine;
public class ScreenCoordinates : MonoBehaviour
{
void Update()
{
Vector3 mousePos = Input.mousePosition;
// 화면 크기 정보
float screenWidth = Screen.width; // 화면 너비 (픽셀)
float screenHeight = Screen.height; // 화면 높이 (픽셀)
Debug.Log($"화면 크기: {screenWidth} x {screenHeight}");
Debug.Log($"마우스 위치: ({mousePos.x}, {mousePos.y})");
// 화면 중앙 기준으로 정규화 (0~1)
float normalizedX = mousePos.x / screenWidth;
float normalizedY = mousePos.y / screenHeight;
Debug.Log($"정규화된 위치: ({normalizedX}, {normalizedY})");
}
}
마우스 입력 함수(function) 비교
GetMouseButtonDown() - 클릭 시작
using UnityEngine;
public class MouseDown : MonoBehaviour
{
void Update()
{
// 마우스 버튼을 누른 순간 한 번만 true 반환
if (Input.GetMouseButtonDown(0)) // 왼쪽 버튼
{
Debug.Log("마우스 버튼을 눌렀습니다!");
}
}
}
특징:
- 버튼을 누른 순간 한 번만 true 반환(return)
- 드래그 시작 지점을 저장할 때 사용
- 연속 입력이 아닌 단발 입력 감지
GetMouseButton() - 누르고 있는 동안
using UnityEngine;
public class MouseButton : MonoBehaviour
{
void Update()
{
// 마우스 버튼을 누르고 있는 동안 계속 true 반환
if (Input.GetMouseButton(0)) // 왼쪽 버튼
{
Debug.Log("마우스 버튼을 누르고 있습니다!");
}
}
}
특징:
- 버튼을 누르고 있는 동안 계속 true 반환(return)
- 드래그 중인지 확인할 때 사용
- 연속 입력 감지
GetMouseButtonUp() - 클릭 종료
using UnityEngine;
public class MouseUp : MonoBehaviour
{
void Update()
{
// 마우스 버튼을 뗀 순간 한 번만 true 반환
if (Input.GetMouseButtonUp(0)) // 왼쪽 버튼
{
Debug.Log("마우스 버튼을 뗐습니다!");
}
}
}
특징:
- 버튼을 뗀 순간 한 번만 true 반환(return)
- 드래그 종료 지점을 저장할 때 사용
- 단발 입력 감지
세 가지 함수(function) 비교
using UnityEngine;
public class MouseComparison : MonoBehaviour
{
void Update()
{
// 1. 클릭 시작 (한 번만)
if (Input.GetMouseButtonDown(0))
{
Debug.Log("클릭 시작!");
}
// 2. 누르고 있는 동안 (계속)
if (Input.GetMouseButton(0))
{
Debug.Log("누르고 있음...");
}
// 3. 클릭 종료 (한 번만)
if (Input.GetMouseButtonUp(0))
{
Debug.Log("클릭 종료!");
}
}
}
transform.Translate() 메서드(method)
기본 사용법
using UnityEngine;
public class TranslateExample : MonoBehaviour
{
void Update()
{
// X축으로 1 단위 이동
transform.Translate(1, 0, 0);
// Y축으로 1 단위 이동
transform.Translate(0, 1, 0);
// Z축으로 1 단위 이동
transform.Translate(0, 0, 1);
}
}
Translate() 파라미터
transform.Translate(x, y, z);
- x: X축 이동 거리
- y: Y축 이동 거리
- z: Z축 이동 거리
- 주의: 로컬 좌표계 기준으로 이동 (기본값)
시간 기반 이동
using UnityEngine;
public class TimeBasedTranslate : MonoBehaviour
{
public float speed = 5f; // 초당 이동 거리
void Update()
{
// 초당 speed 단위씩 X축으로 이동
// Time.deltaTime을 곱하여 프레임률과 무관하게 일정한 속도 유지
transform.Translate(speed * Time.deltaTime, 0, 0);
}
}
Translate() vs position 직접 변경
using UnityEngine;
public class TranslateVsPosition : MonoBehaviour
{
public float speed = 5f;
void Update()
{
// 방법 1: Translate() 사용 (상대 이동)
transform.Translate(speed * Time.deltaTime, 0, 0);
// 방법 2: position 직접 변경 (절대 위치)
// transform.position = transform.position + new Vector3(speed * Time.deltaTime, 0, 0);
// 방법 3: position 직접 변경 (간단한 형태)
// transform.position += new Vector3(speed * Time.deltaTime, 0, 0);
}
}
차이점:
- Translate(): 로컬 좌표계 기준 상대 이동 (회전된 오브젝트에 유용)
- position: 월드 좌표계 기준 절대 위치 설정
마우스 드래그로 자동차 제어 구현
기본 자동차 컨트롤러
using UnityEngine;
public class CarController : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false; // 드래그 진행 중인지 확인하는 플래그
void Update()
{
// 마우스 버튼을 누른 순간 시작 위치 저장
if (Input.GetMouseButtonDown(0) && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // 드래그 시작
}
// 마우스 버튼을 뗀 순간 종료 위치 저장 및 속도 계산
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
// 드래그 거리 계산 (X축 기준)
float dragGap = endPosition.x - startPosition.x;
// 드래그 거리를 속도로 변환
carSpeed = dragGap * 0.001f;
isDragging = false; // 드래그 종료
}
// 자동차 이동
transform.Translate(carSpeed, 0, 0);
// 감속 처리
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
else
{
carSpeed *= 0.98f; // 매 프레임 2% 감소
}
}
}
완전한 자동차 컨트롤러 예제
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 마우스 드래그로 자동차를 제어하는 컨트롤러 클래스
/// 마우스를 클릭하고 드래그한 거리에 따라 자동차의 속도가 결정됩니다.
/// 한 번만 드래그할 수 있으며, 자동차가 완전히 멈춘 상태에서만 새로운 드래그가 가능합니다.
/// </summary>
public class CarController2 : MonoBehaviour
{
/// <summary>
/// 자동차의 현재 이동 속도
/// 양수면 오른쪽, 음수면 왼쪽으로 이동합니다.
/// </summary>
public float carSpeed = 0f;
/// <summary>
/// 마우스 드래그 시작 위치
/// GetMouseButtonDown()에서 저장하고, GetMouseButtonUp()에서 사용합니다.
/// </summary>
Vector2 startPosition;
/// <summary>
/// 드래그 진행 중인지 확인하는 플래그
/// true면 현재 드래그 중, false면 드래그 중이 아님
/// </summary>
bool isDragging = false;
/// <summary>
/// 한 번이라도 드래그가 발생했는지 확인하는 플래그
/// true면 이미 드래그했으므로 더 이상 드래그 불가
/// </summary>
bool hasDraggedOnce = false;
void Start()
{
// 초기화 (현재는 사용하지 않지만 필요시 초기 설정을 여기에 추가)
}
void Update()
{
// Unity 마우스 입력 함수 참고 정보
// GetMouseButton(0): 마우스 버튼을 누르고 있는 동안 true 반환 (연속 입력 감지)
// GetMouseButtonDown(0): 마우스 버튼을 누른 순간 한 번만 true 반환 (단발 입력 감지)
// GetMouseButtonUp(0): 마우스 버튼을 떼는 순간 한 번만 true 반환 (단발 입력 감지)
// 한 번도 드래그하지 않았고, 드래그가 진행 중이 아니고, 자동차가 완전히 멈춰있을 때만 새로운 드래그 시작 가능
// 조건: !hasDraggedOnce (아직 드래그 안 함) && !isDragging (드래그 중 아님) && carSpeed == 0f (완전히 정지)
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // 드래그 시작 플래그 설정
}
// 드래그 중일 때만 드래그 종료 처리
if (Input.GetMouseButtonUp(0) && isDragging)
{
// 드래그 종료 위치
Vector2 endPosition = Input.mousePosition;
// 드래그 거리 계산 (X축 기준)
// 양수면 오른쪽으로 드래그, 음수면 왼쪽으로 드래그
float dragGap = endPosition.x - startPosition.x;
// 드래그 거리를 속도로 변환
// 0.005f는 드래그 거리를 속도로 변환하는 비율
// 0.23f는 추가 감쇠 계수 (속도 조절)
carSpeed = (dragGap * 0.005f) * 0.23f;
isDragging = false; // 드래그 종료 플래그 해제
hasDraggedOnce = true; // 드래그가 한 번 발생했음을 표시 (더 이상 드래그 불가)
}
// 자동차를 현재 속도만큼 X축으로 이동
// Translate(x, y, z): 로컬 좌표계 기준으로 이동
transform.Translate(carSpeed, 0, 0);
// 감속 처리
// 속도가 거의 0에 도달했으면 완전히 정지
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
else
{
// 속도를 매 프레임마다 98%로 감소 (2% 감소)
// 자연스러운 감속 효과를 만듭니다.
carSpeed *= 0.98f;
}
}
}
드래그 거리 계산
기본 드래그 거리 계산
using UnityEngine;
public class DragDistance : MonoBehaviour
{
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
// 드래그 거리 계산
float distance = endPos.x - startPos.x;
Debug.Log($"드래그 거리: {distance} 픽셀");
}
}
}
양방향 드래그 처리
using UnityEngine;
public class BidirectionalDrag : MonoBehaviour
{
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
if (dragGap > 0)
{
Debug.Log("오른쪽으로 드래그!");
}
else if (dragGap < 0)
{
Debug.Log("왼쪽으로 드래그!");
}
else
{
Debug.Log("드래그 없음 (클릭만)");
}
}
}
}
2D 드래그 거리 계산
using UnityEngine;
public class DragDistance2D : MonoBehaviour
{
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
// X축 거리
float distanceX = endPos.x - startPos.x;
// Y축 거리
float distanceY = endPos.y - startPos.y;
// 전체 거리 (피타고라스 정리)
float totalDistance = Mathf.Sqrt(distanceX * distanceX + distanceY * distanceY);
Debug.Log($"X 거리: {distanceX}, Y 거리: {distanceY}, 전체 거리: {totalDistance}");
}
}
}
속도 변환
드래그 거리를 속도로 변환
using UnityEngine;
public class DragToSpeed : MonoBehaviour
{
public float speedMultiplier = 0.001f; // 속도 변환 비율
public float carSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
// 드래그 거리를 속도로 변환
carSpeed = dragGap * speedMultiplier;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
속도 제한
using UnityEngine;
public class SpeedLimit : MonoBehaviour
{
public float maxSpeed = 10f; // 최대 속도
public float carSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
float newSpeed = dragGap * 0.001f;
// 속도 제한 적용
carSpeed = Mathf.Clamp(newSpeed, -maxSpeed, maxSpeed);
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
상태 관리
플래그 변수(variable)로 드래그 상태 관리
using UnityEngine;
public class DragStateManagement : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false; // 드래그 진행 중인지 확인
bool hasDraggedOnce = false; // 한 번이라도 드래그했는지 확인
void Update()
{
// 조건: 아직 드래그 안 함 && 드래그 중 아님 && 완전히 정지
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // 드래그 시작
}
// 드래그 중일 때만 종료 처리
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
float dragGap = endPosition.x - startPosition.x;
carSpeed = dragGap * 0.001f;
isDragging = false; // 드래그 종료
hasDraggedOnce = true; // 한 번 드래그했음을 표시
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
}
}
플래그 변수(variable)의 역할
-
isDragging: 현재 드래그가 진행 중인지 확인
true: 드래그 중, 새로운 드래그 시작 불가false: 드래그 중 아님, 드래그 시작 가능
-
hasDraggedOnce: 한 번이라도 드래그했는지 확인
true: 이미 드래그했음, 더 이상 드래그 불가false: 아직 드래그 안 함, 드래그 가능
실전 활용 예시
예시 1: 한 번만 드래그 가능한 자동차
using UnityEngine;
public class OneTimeDrag : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false;
bool hasDraggedOnce = false; // 한 번만 드래그 가능
void Update()
{
// 한 번도 드래그하지 않았고, 드래그 중이 아니고, 정지 상태일 때만 드래그 시작
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true;
}
// 드래그 중일 때만 종료 처리
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
float dragGap = endPosition.x - startPosition.x;
carSpeed = dragGap * 0.001f;
isDragging = false;
hasDraggedOnce = true; // 한 번 드래그했으므로 더 이상 불가
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
}
}
예시 2: 최소 드래그 거리 설정
using UnityEngine;
public class MinDragDistance : MonoBehaviour
{
public float minDragDistance = 50f; // 최소 드래그 거리 (픽셀)
public float carSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
// 최소 드래그 거리 확인
if (Mathf.Abs(dragGap) >= minDragDistance)
{
carSpeed = dragGap * 0.001f;
}
else
{
// 최소 거리 미만이면 무시 (클릭으로 간주)
carSpeed = 0f;
}
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
예시 2: 드래그 방향 표시
using UnityEngine;
public class DragDirection : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
// 드래그 방향 표시
if (dragGap > 0)
{
Debug.Log("→ 오른쪽으로 드래그!");
}
else if (dragGap < 0)
{
Debug.Log("← 왼쪽으로 드래그!");
}
carSpeed = dragGap * 0.001f;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
예시 3: 드래그 속도에 따른 가속도 조절
using UnityEngine;
public class VariableAcceleration : MonoBehaviour
{
public float carSpeed = 0f;
public float fastDragMultiplier = 0.002f; // 빠른 드래그 배율
public float slowDragMultiplier = 0.0005f; // 느린 드래그 배율
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
float dragDistance = Mathf.Abs(dragGap);
// 드래그 속도에 따라 배율 선택
float multiplier = dragDistance > 200f ? fastDragMultiplier : slowDragMultiplier;
carSpeed = dragGap * multiplier;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
예시 4: Y축 드래그로 점프
using UnityEngine;
public class JumpWithDrag : MonoBehaviour
{
public float jumpSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.y - startPos.y; // Y축 드래그
// 위로 드래그하면 점프
if (dragGap > 0)
{
jumpSpeed = dragGap * 0.01f;
}
}
// Y축으로 이동 (점프)
transform.Translate(0, jumpSpeed, 0);
jumpSpeed *= 0.95f;
// 중력 효과 (아래로 떨어짐)
if (transform.position.y > 0)
{
transform.Translate(0, -0.1f, 0);
}
else
{
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
jumpSpeed = 0f;
}
}
}
주의사항
- 화면 좌표계:
Input.mousePosition은 화면 좌표계를 사용하므로, 월드 좌표로 변환하려면Camera.ScreenToWorldPoint()를 사용해야 합니다 - 드래그 거리: 픽셀 단위이므로 해상도에 따라 값이 달라질 수 있습니다
- 속도 변환 비율: 드래그 거리를 속도로 변환하는 비율은 게임에 맞게 조절해야 합니다
- 음수 속도: 왼쪽으로 드래그하면 음수 값이 나오므로
Mathf.Abs()를 사용하여 절댓값으로 비교해야 할 수 있습니다
실전 활용 팁
팁 1: Inspector에서 속도 조절
using UnityEngine;
public class InspectorCarControl : MonoBehaviour
{
[Header("속도 설정")]
public float carSpeed = 0f;
[Header("드래그 변환 비율")]
public float dragToSpeedRatio = 0.001f;
public float speedDamping = 0.23f;
[Header("감속 설정")]
[Range(0.9f, 0.99f)]
public float decelerationRate = 0.98f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
carSpeed = (dragGap * dragToSpeedRatio) * speedDamping;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= decelerationRate;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
팁 2: 드래그 중 시각적 피드백
using UnityEngine;
public class DragFeedback : MonoBehaviour
{
public float carSpeed = 0f;
public LineRenderer dragLine; // 드래그 선 표시용
Vector2 startPos;
bool isDragging = false;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
isDragging = true;
// 드래그 선 시작
if (dragLine != null)
{
dragLine.enabled = true;
}
}
// 드래그 중일 때 선 업데이트
if (isDragging && Input.GetMouseButton(0))
{
Vector2 currentPos = Input.mousePosition;
// 드래그 선 표시 로직...
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
carSpeed = dragGap * 0.001f;
isDragging = false;
// 드래그 선 숨기기
if (dragLine != null)
{
dragLine.enabled = false;
}
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
팁 3: 부드러운 감속
using UnityEngine;
public class SmoothDeceleration : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
carSpeed = dragGap * 0.001f;
}
transform.Translate(carSpeed, 0, 0);
// 속도가 낮을수록 더 빠르게 감속
if (Mathf.Abs(carSpeed) < 1f)
{
carSpeed *= 0.95f; // 더 빠른 감속
}
else
{
carSpeed *= 0.98f; // 일반 감속
}
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}