룰렛 회전이란?
룰렛 회전 제어는 Unity에서 오브젝트를 회전시키고, 사용자 입력에 따라 회전을 시작하거나 멈추는 기능입니다. 게임에서 룰렛, 휠, 회전하는 장식품 등을 만들 때 사용합니다.
기본 개념
- 회전 속도: 초당 회전 각도 (도 단위)
- 감속 효과: 회전 속도를 점진적으로 줄여 자연스럽게 멈추는 효과
- 입력 처리: 마우스 클릭으로 회전 시작/정지 제어
- 프레임별 업데이트: Update() 메서드(method)에서 매 프레임마다 회전 적용
transform.Rotate() 메서드(method)
기본 사용법
using UnityEngine;
public class RotateObject : MonoBehaviour
{
void Update()
{
// Z축 기준으로 90도 회전
transform.Rotate(0, 0, 90);
// X축 기준으로 회전
transform.Rotate(90, 0, 0);
// Y축 기준으로 회전
transform.Rotate(0, 90, 0);
}
}
Rotate() 파라미터
transform.Rotate(x, y, z);
- x: X축 기준 회전 각도 (도 단위)
- y: Y축 기준 회전 각도 (도 단위)
- z: Z축 기준 회전 각도 (도 단위)
- 주의: 각도는 도(degree) 단위이며, 라디안이 아닙니다
시간 기반 회전
using UnityEngine;
public class SmoothRotate : MonoBehaviour
{
public float rotateSpeed = 90f; // 초당 90도
void Update()
{
// 초당 rotateSpeed도씩 회전
// Time.deltaTime을 곱하여 프레임률과 무관하게 일정한 속도 유지
transform.Rotate(0, 0, rotateSpeed * Time.deltaTime);
}
}
마우스 입력 처리
Input.GetMouseButtonDown()
using UnityEngine;
public class MouseInput : MonoBehaviour
{
void Update()
{
// 마우스 왼쪽 버튼 클릭 감지 (한 번만 true)
if (Input.GetMouseButtonDown(0))
{
Debug.Log("왼쪽 클릭!");
}
// 마우스 오른쪽 버튼 클릭 감지
if (Input.GetMouseButtonDown(1))
{
Debug.Log("오른쪽 클릭!");
}
// 마우스 가운데 버튼 클릭 감지
if (Input.GetMouseButtonDown(2))
{
Debug.Log("가운데 클릭!");
}
}
}
마우스 버튼 번호
- 0: 왼쪽 버튼
- 1: 오른쪽 버튼
- 2: 가운데 버튼 (휠 클릭)
Input.GetMouseButton() vs GetMouseButtonDown()
using UnityEngine;
public class MouseDifference : MonoBehaviour
{
void Update()
{
// GetMouseButtonDown: 클릭한 순간만 true (한 번만)
if (Input.GetMouseButtonDown(0))
{
Debug.Log("클릭 시작!");
}
// GetMouseButton: 버튼을 누르고 있는 동안 계속 true
if (Input.GetMouseButton(0))
{
Debug.Log("누르고 있음!");
}
// GetMouseButtonUp: 버튼을 뗀 순간만 true (한 번만)
if (Input.GetMouseButtonUp(0))
{
Debug.Log("클릭 종료!");
}
}
}
룰렛 회전 컨트롤러 구현
기본 룰렛 컨트롤러
using UnityEngine;
public class RouletteController : MonoBehaviour
{
// 회전 속도 (초당 각도)
public float rotateSpeed = 0f;
void Update()
{
// 마우스 왼쪽 클릭으로 회전 시작
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
// 랜덤한 초기 속도 설정
rotateSpeed = Random.Range(15f, 30f);
}
// 회전 적용
transform.Rotate(0, 0, rotateSpeed);
// 속도 감소 (자연스러운 감속)
rotateSpeed *= 0.986f;
// 거의 정지했으면 완전히 정지
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
브레이크 기능 추가
using UnityEngine;
public class RouletteControllerWithBrake : MonoBehaviour
{
public float rotateSpeed = 0f;
void Update()
{
// 왼쪽 클릭: 회전 시작
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(15f, 30f);
}
// 오른쪽 클릭: 브레이크
if (Input.GetMouseButtonDown(1))
{
// 속도를 20%로 급격히 감소
rotateSpeed *= 0.2f;
Debug.Log("브레이크 작동!");
}
// 회전 적용
transform.Rotate(0, 0, rotateSpeed);
// 자연스러운 감속
rotateSpeed *= 0.986f;
// 정지 처리
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
감속 효과 구현
곱셈을 이용한 감속
// 매 프레임마다 속도를 일정 비율로 감소
rotateSpeed *= 0.986f; // 1.4% 감소 (98.6% 유지)
감속 비율의 의미
// 빠른 감속 (더 빨리 멈춤)
rotateSpeed *= 0.9f; // 10% 감소
// 중간 감속
rotateSpeed *= 0.986f; // 1.4% 감소
// 느린 감속 (더 천천히 멈춤)
rotateSpeed *= 0.99f; // 1% 감소
뺄셈을 이용한 감속 (선형 감속)
using UnityEngine;
public class LinearDeceleration : MonoBehaviour
{
public float rotateSpeed = 30f;
public float deceleration = 0.5f; // 초당 감소량
void Update()
{
transform.Rotate(0, 0, rotateSpeed);
// 일정량씩 감소 (선형 감속)
rotateSpeed -= deceleration * Time.deltaTime;
// 0 이하로 내려가지 않도록
if (rotateSpeed < 0f)
{
rotateSpeed = 0f;
}
}
}
곱셈 vs 뺄셈 감속 비교
// 곱셈 감속 (지수 감속)
// - 처음엔 빠르게 감소, 나중엔 천천히 감소
// - 자연스러운 감속 효과
rotateSpeed *= 0.986f;
// 뺄셈 감속 (선형 감속)
// - 일정한 속도로 감소
// - 예측 가능한 감속
rotateSpeed -= 0.5f;
상태 관리
변수(variable)로 상태 관리하기
using UnityEngine;
public class StateManagement : MonoBehaviour
{
public float rotateSpeed = 0f;
void Update()
{
// rotateSpeed == 0f로 정지 상태 확인
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
// 정지 상태일 때만 회전 시작
rotateSpeed = Random.Range(15f, 30f);
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= 0.986f;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f; // 정지 상태로 전환
}
}
}
bool 변수(variable)로 상태 관리
using UnityEngine;
public class BoolStateManagement : MonoBehaviour
{
public float rotateSpeed = 0f;
private bool isRotating = false;
void Update()
{
// 정지 상태일 때만 회전 시작
if (Input.GetMouseButtonDown(0) && !isRotating)
{
rotateSpeed = Random.Range(15f, 30f);
isRotating = true;
}
if (isRotating)
{
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= 0.986f;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
isRotating = false; // 정지 상태로 전환
}
}
}
}
완전한 룰렛 컨트롤러 예제
아이디어 버전 (간단한 버전)
using UnityEngine;
/// <summary>
/// 룰렛 회전을 제어하는 컨트롤러 클래스 (아이디어 버전)
/// 마우스 왼쪽 클릭으로 룰렛을 회전시키고, 오른쪽 클릭으로 급격한 감속(브레이크) 기능을 제공합니다.
/// 플래그 변수 대신 rotateSpeed 값으로 회전 상태를 관리하는 간단한 버전입니다.
/// </summary>
public class RouletteController_idea : MonoBehaviour
{
/// <summary>
/// 룰렛의 현재 회전 속도 (초당 각도)
/// 0이면 정지 상태, 0보다 크면 회전 중 상태를 나타냅니다.
/// 매 프레임마다 감소하여 자연스러운 감속 효과를 만듭니다.
/// </summary>
public float rotateSpeed = 0f;
/// <summary>
/// 매 프레임마다 호출되는 업데이트 메서드
/// 마우스 입력 감지, 룰렛 회전 처리, 속도 감소 로직을 처리합니다.
/// </summary>
void Update()
{
// 마우스 왼쪽 버튼 클릭 감지 및 회전 시작 조건 확인
// 조건: 마우스 왼쪽 클릭 && 현재 회전 속도가 0 (정지 상태)
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
// 랜덤한 초기 회전 속도 설정 (15도 ~ 30도 사이의 랜덤 값)
rotateSpeed = Random.Range(15f, 30f);
}
// 마우스 오른쪽 버튼 클릭 감지 (브레이크 기능)
if (Input.GetMouseButtonDown(1))
{
Debug.Log("브레이크 작동!");
// 회전 속도를 현재 속도의 20%로 급격히 감소시킴
rotateSpeed *= 0.2f;
}
// 매 프레임마다 Z축을 기준으로 회전 적용
transform.Rotate(0, 0, rotateSpeed);
// 회전 속도를 매 프레임마다 98.6%로 감소시킴 (1.4% 감소)
// 자연스러운 감속 효과를 만듭니다.
rotateSpeed *= 0.986f;
// 회전 속도가 거의 0에 도달했는지 확인 (0.05도 이하)
if (rotateSpeed <= 0.05f)
{
// 회전 속도를 완전히 0으로 설정하여 정지
rotateSpeed = 0f;
}
}
}
실전 활용 예시
예시 1: 회전 속도 조절 가능한 룰렛
using UnityEngine;
public class AdjustableRoulette : MonoBehaviour
{
public float rotateSpeed = 0f;
public float minSpeed = 15f; // 최소 초기 속도
public float maxSpeed = 30f; // 최대 초기 속도
public float deceleration = 0.986f; // 감속 비율
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(minSpeed, maxSpeed);
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= deceleration;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
예시 2: 회전 방향 제어
using UnityEngine;
public class DirectionalRoulette : MonoBehaviour
{
public float rotateSpeed = 0f;
public bool rotateClockwise = true; // 시계 방향 여부
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
float speed = Random.Range(15f, 30f);
// 시계 방향이 아니면 음수로 설정
rotateSpeed = rotateClockwise ? speed : -speed;
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= 0.986f;
// 음수 속도도 처리
if (Mathf.Abs(rotateSpeed) <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
예시 3: 회전 완료 이벤트(event)
using UnityEngine;
using System;
public class RouletteWithEvent : MonoBehaviour
{
public float rotateSpeed = 0f;
public event Action OnRotationComplete; // 회전 완료 이벤트
private bool wasRotating = false;
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(15f, 30f);
wasRotating = true;
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= 0.986f;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
// 회전이 완료되었을 때 이벤트 발생
if (wasRotating)
{
wasRotating = false;
OnRotationComplete?.Invoke();
Debug.Log("회전 완료!");
}
}
}
}
예시 4: 키보드 입력으로 제어
using UnityEngine;
public class KeyboardRoulette : MonoBehaviour
{
public float rotateSpeed = 0f;
void Update()
{
// Space 키로 회전 시작
if (Input.GetKeyDown(KeyCode.Space) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(15f, 30f);
}
// B 키로 브레이크
if (Input.GetKeyDown(KeyCode.B))
{
rotateSpeed *= 0.2f;
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= 0.986f;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
주의사항
- 프레임률 독립성:
Time.deltaTime을 사용하지 않으면 프레임률에 따라 회전 속도가 달라질 수 있습니다 - 정지 조건:
rotateSpeed <= 0.05f같은 임계값을 사용하여 부드러운 정지 효과를 만듭니다 - 상태 확인: 회전 중에는 새로운 회전을 시작하지 않도록 조건을 확인해야 합니다
- 음수 속도: 반시계 방향 회전을 원하면 음수 값을 사용할 수 있습니다
실전 활용 팁
팁 1: Inspector에서 속도 조절
using UnityEngine;
public class InspectorRoulette : MonoBehaviour
{
[Header("회전 설정")]
public float rotateSpeed = 0f;
[Header("초기 속도 범위")]
public float minInitialSpeed = 15f;
public float maxInitialSpeed = 30f;
[Header("감속 설정")]
[Range(0.9f, 0.99f)]
public float decelerationRate = 0.986f;
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(minInitialSpeed, maxInitialSpeed);
}
transform.Rotate(0, 0, rotateSpeed);
rotateSpeed *= decelerationRate;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
팁 2: 회전 각도 제한
using UnityEngine;
public class LimitedRotation : MonoBehaviour
{
public float rotateSpeed = 0f;
public float currentAngle = 0f; // 현재 누적 각도
public float maxAngle = 360f; // 최대 회전 각도
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(15f, 30f);
currentAngle = 0f; // 각도 초기화
}
if (rotateSpeed > 0f)
{
float rotation = rotateSpeed;
// 최대 각도 제한
if (currentAngle + rotation > maxAngle)
{
rotation = maxAngle - currentAngle;
rotateSpeed = 0f;
}
transform.Rotate(0, 0, rotation);
currentAngle += rotation;
rotateSpeed *= 0.986f;
if (rotateSpeed <= 0.05f)
{
rotateSpeed = 0f;
}
}
}
}
팁 3: 부드러운 정지
using UnityEngine;
public class SmoothStop : MonoBehaviour
{
public float rotateSpeed = 0f;
public float stopThreshold = 0.1f; // 정지 임계값
void Update()
{
if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
{
rotateSpeed = Random.Range(15f, 30f);
}
transform.Rotate(0, 0, rotateSpeed);
// 속도가 낮을수록 더 빠르게 감속
if (rotateSpeed < 1f)
{
rotateSpeed *= 0.95f; // 더 빠른 감속
}
else
{
rotateSpeed *= 0.986f; // 일반 감속
}
if (rotateSpeed <= stopThreshold)
{
rotateSpeed = 0f;
}
}
}