룰렛 회전 제어

Unity에서 룰렛 회전을 제어하는 방법을 학습합니다. 마우스 입력 처리, transform.Rotate() 사용, 자연스러운 감속 효과 구현 등을 다룹니다.

룰렛 회전이란?

룰렛 회전 제어는 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;
        }
    }
}

주의사항

  1. 프레임률 독립성: Time.deltaTime을 사용하지 않으면 프레임률에 따라 회전 속도가 달라질 수 있습니다
  2. 정지 조건: rotateSpeed <= 0.05f 같은 임계값을 사용하여 부드러운 정지 효과를 만듭니다
  3. 상태 확인: 회전 중에는 새로운 회전을 시작하지 않도록 조건을 확인해야 합니다
  4. 음수 속도: 반시계 방향 회전을 원하면 음수 값을 사용할 수 있습니다

실전 활용 팁

팁 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;
        }
    }
}

← 목차로 돌아가기