Roulette Rotation Control

Learn how to control roulette rotation in Unity. Covers mouse input handling, using transform.Rotate(), and implementing natural deceleration effects.

What is Roulette Rotation?

Roulette rotation control is a feature in Unity that rotates objects and allows users to start or stop rotation based on input. It's used to create roulettes, wheels, rotating decorations, and similar objects in games.

Basic Concepts

  • Rotation Speed: Rotation angle per second (in degrees)
  • Deceleration Effect: Gradually reducing rotation speed to stop naturally
  • Input Handling: Controlling rotation start/stop with mouse clicks
  • Frame-by-Frame Update: Applying rotation every frame in the Update() method

transform.Rotate() Method

Basic Usage

using UnityEngine;

public class RotateObject : MonoBehaviour
{
    void Update()
    {
        // Rotate 90 degrees around Z-axis
        transform.Rotate(0, 0, 90);
        
        // Rotate around X-axis
        transform.Rotate(90, 0, 0);
        
        // Rotate around Y-axis
        transform.Rotate(0, 90, 0);
    }
}

Rotate() Parameters

transform.Rotate(x, y, z);
  • x: Rotation angle around X-axis (in degrees)
  • y: Rotation angle around Y-axis (in degrees)
  • z: Rotation angle around Z-axis (in degrees)
  • Note: Angles are in degrees, not radians

Time-based Rotation

using UnityEngine;

public class SmoothRotate : MonoBehaviour
{
    public float rotateSpeed = 90f;  // 90 degrees per second
    
    void Update()
    {
        // Rotate at rotateSpeed degrees per second
        // Multiply by Time.deltaTime to maintain constant speed regardless of framerate
        transform.Rotate(0, 0, rotateSpeed * Time.deltaTime);
    }
}

Mouse Input Handling

Input.GetMouseButtonDown()

using UnityEngine;

public class MouseInput : MonoBehaviour
{
    void Update()
    {
        // Detect left mouse button click (true only once)
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("Left click!");
        }
        
        // Detect right mouse button click
        if (Input.GetMouseButtonDown(1))
        {
            Debug.Log("Right click!");
        }
        
        // Detect middle mouse button click
        if (Input.GetMouseButtonDown(2))
        {
            Debug.Log("Middle click!");
        }
    }
}

Mouse Button Numbers

  • 0: Left button
  • 1: Right button
  • 2: Middle button (wheel click)

Input.GetMouseButton() vs GetMouseButtonDown()

using UnityEngine;

public class MouseDifference : MonoBehaviour
{
    void Update()
    {
        // GetMouseButtonDown: true only at the moment of click (once)
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("Click started!");
        }
        
        // GetMouseButton: true while button is held down
        if (Input.GetMouseButton(0))
        {
            Debug.Log("Holding!");
        }
        
        // GetMouseButtonUp: true only when button is released (once)
        if (Input.GetMouseButtonUp(0))
        {
            Debug.Log("Click ended!");
        }
    }
}

Implementing Roulette Controller

Basic Roulette Controller

using UnityEngine;

public class RouletteController : MonoBehaviour
{
    // Rotation speed (degrees per second)
    public float rotateSpeed = 0f;
    
    void Update()
    {
        // Start rotation on left mouse click
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            // Set random initial speed
            rotateSpeed = Random.Range(15f, 30f);
        }
        
        // Apply rotation
        transform.Rotate(0, 0, rotateSpeed);
        
        // Decrease speed (natural deceleration)
        rotateSpeed *= 0.986f;
        
        // Stop completely when almost stopped
        if (rotateSpeed <= 0.05f)
        {
            rotateSpeed = 0f;
        }
    }
}

Adding Brake Functionality

using UnityEngine;

public class RouletteControllerWithBrake : MonoBehaviour
{
    public float rotateSpeed = 0f;
    
    void Update()
    {
        // Left click: Start rotation
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            rotateSpeed = Random.Range(15f, 30f);
        }
        
        // Right click: Brake
        if (Input.GetMouseButtonDown(1))
        {
            // Rapidly reduce speed to 20%
            rotateSpeed *= 0.2f;
            Debug.Log("Brake activated!");
        }
        
        // Apply rotation
        transform.Rotate(0, 0, rotateSpeed);
        
        // Natural deceleration
        rotateSpeed *= 0.986f;
        
        // Stop handling
        if (rotateSpeed <= 0.05f)
        {
            rotateSpeed = 0f;
        }
    }
}

Implementing Deceleration Effect

Deceleration Using Multiplication

// Reduce speed by a constant ratio each frame
rotateSpeed *= 0.986f;  // 1.4% decrease (maintain 98.6%)

Meaning of Deceleration Ratio

// Fast deceleration (stops quickly)
rotateSpeed *= 0.9f;   // 10% decrease

// Medium deceleration
rotateSpeed *= 0.986f;  // 1.4% decrease

// Slow deceleration (stops slowly)
rotateSpeed *= 0.99f;   // 1% decrease

Deceleration Using Subtraction (Linear Deceleration)

using UnityEngine;

public class LinearDeceleration : MonoBehaviour
{
    public float rotateSpeed = 30f;
    public float deceleration = 0.5f;  // Decrease per second
    
    void Update()
    {
        transform.Rotate(0, 0, rotateSpeed);
        
        // Decrease by constant amount (linear deceleration)
        rotateSpeed -= deceleration * Time.deltaTime;
        
        // Prevent going below 0
        if (rotateSpeed < 0f)
        {
            rotateSpeed = 0f;
        }
    }
}

Multiplication vs Subtraction Deceleration Comparison

// Multiplication deceleration (exponential deceleration)
// - Fast decrease at first, slow decrease later
// - Natural deceleration effect
rotateSpeed *= 0.986f;

// Subtraction deceleration (linear deceleration)
// - Constant speed decrease
// - Predictable deceleration
rotateSpeed -= 0.5f;

State Management

Managing State with Variables

using UnityEngine;

public class StateManagement : MonoBehaviour
{
    public float rotateSpeed = 0f;
    
    void Update()
    {
        // Check stopped state with rotateSpeed == 0f
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            // Start rotation only when stopped
            rotateSpeed = Random.Range(15f, 30f);
        }
        
        transform.Rotate(0, 0, rotateSpeed);
        rotateSpeed *= 0.986f;
        
        if (rotateSpeed <= 0.05f)
        {
            rotateSpeed = 0f;  // Transition to stopped state
        }
    }
}

Managing State with bool Variable

using UnityEngine;

public class BoolStateManagement : MonoBehaviour
{
    public float rotateSpeed = 0f;
    private bool isRotating = false;
    
    void Update()
    {
        // Start rotation only when stopped
        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;  // Transition to stopped state
            }
        }
    }
}

Complete Roulette Controller Example

Idea Version (Simple Version)

using UnityEngine;

/// <summary>
/// Controller class for roulette rotation (idea version)
/// Rotates roulette with left mouse click and provides rapid deceleration (brake) with right click.
/// Simple version that manages rotation state with rotateSpeed value instead of flag variables.
/// </summary>
public class RouletteController_idea : MonoBehaviour
{
    /// <summary>
    /// Current rotation speed of the roulette (degrees per second)
    /// 0 means stopped state, greater than 0 means rotating state.
    /// Decreases each frame to create natural deceleration effect.
    /// </summary>
    public float rotateSpeed = 0f;

    /// <summary>
    /// Update method called every frame
    /// Handles mouse input detection, roulette rotation, and speed decrease logic.
    /// </summary>
    void Update()
    {
        // Detect left mouse button click and check rotation start condition
        // Condition: Left mouse click && current rotation speed is 0 (stopped state)
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            // Set random initial rotation speed (random value between 15 and 30 degrees)
            rotateSpeed = Random.Range(15f, 30f);
        }

        // Detect right mouse button click (brake functionality)
        if (Input.GetMouseButtonDown(1))
        {
            Debug.Log("Brake activated!");
            
            // Rapidly reduce rotation speed to 20% of current speed
            rotateSpeed *= 0.2f;
        }

        // Apply rotation around Z-axis every frame
        transform.Rotate(0, 0, rotateSpeed);

        // Reduce rotation speed to 98.6% each frame (1.4% decrease)
        // Creates natural deceleration effect.
        rotateSpeed *= 0.986f;

        // Check if rotation speed has reached almost 0 (0.05 degrees or less)
        if (rotateSpeed <= 0.05f)
        {
            // Set rotation speed to exactly 0 to stop
            rotateSpeed = 0f;
        }
    }
}

Practical Usage Examples

Example 1: Roulette with Adjustable Rotation Speed

using UnityEngine;

public class AdjustableRoulette : MonoBehaviour
{
    public float rotateSpeed = 0f;
    public float minSpeed = 15f;      // Minimum initial speed
    public float maxSpeed = 30f;      // Maximum initial speed
    public float deceleration = 0.986f;  // Deceleration ratio
    
    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;
        }
    }
}

Example 2: Rotation Direction Control

using UnityEngine;

public class DirectionalRoulette : MonoBehaviour
{
    public float rotateSpeed = 0f;
    public bool rotateClockwise = true;  // Clockwise rotation flag
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            float speed = Random.Range(15f, 30f);
            // Set to negative if not clockwise
            rotateSpeed = rotateClockwise ? speed : -speed;
        }
        
        transform.Rotate(0, 0, rotateSpeed);
        rotateSpeed *= 0.986f;
        
        // Handle negative speed too
        if (Mathf.Abs(rotateSpeed) <= 0.05f)
        {
            rotateSpeed = 0f;
        }
    }
}

Example 3: Rotation Complete Event

using UnityEngine;
using System;

public class RouletteWithEvent : MonoBehaviour
{
    public float rotateSpeed = 0f;
    public event Action OnRotationComplete;  // Rotation complete event
    
    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;
            
            // Trigger event when rotation completes
            if (wasRotating)
            {
                wasRotating = false;
                OnRotationComplete?.Invoke();
                Debug.Log("Rotation complete!");
            }
        }
    }
}

Example 4: Control with Keyboard Input

using UnityEngine;

public class KeyboardRoulette : MonoBehaviour
{
    public float rotateSpeed = 0f;
    
    void Update()
    {
        // Start rotation with Space key
        if (Input.GetKeyDown(KeyCode.Space) && rotateSpeed == 0f)
        {
            rotateSpeed = Random.Range(15f, 30f);
        }
        
        // Brake with B key
        if (Input.GetKeyDown(KeyCode.B))
        {
            rotateSpeed *= 0.2f;
        }
        
        transform.Rotate(0, 0, rotateSpeed);
        rotateSpeed *= 0.986f;
        
        if (rotateSpeed <= 0.05f)
        {
            rotateSpeed = 0f;
        }
    }
}

Notes

  1. Framerate Independence: Without using Time.deltaTime, rotation speed may vary depending on framerate
  2. Stop Condition: Use thresholds like rotateSpeed <= 0.05f to create smooth stop effects
  3. State Check: Must check conditions to prevent starting new rotation while already rotating
  4. Negative Speed: Can use negative values for counter-clockwise rotation

Practical Tips

Tip 1: Adjust Speed in Inspector

using UnityEngine;

public class InspectorRoulette : MonoBehaviour
{
    [Header("Rotation Settings")]
    public float rotateSpeed = 0f;
    
    [Header("Initial Speed Range")]
    public float minInitialSpeed = 15f;
    public float maxInitialSpeed = 30f;
    
    [Header("Deceleration Settings")]
    [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;
        }
    }
}

Tip 2: Rotation Angle Limit

using UnityEngine;

public class LimitedRotation : MonoBehaviour
{
    public float rotateSpeed = 0f;
    public float currentAngle = 0f;  // Current accumulated angle
    public float maxAngle = 360f;    // Maximum rotation angle
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            rotateSpeed = Random.Range(15f, 30f);
            currentAngle = 0f;  // Reset angle
        }
        
        if (rotateSpeed > 0f)
        {
            float rotation = rotateSpeed;
            
            // Maximum angle limit
            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;
            }
        }
    }
}

Tip 3: Smooth Stop

using UnityEngine;

public class SmoothStop : MonoBehaviour
{
    public float rotateSpeed = 0f;
    public float stopThreshold = 0.1f;  // Stop threshold
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0) && rotateSpeed == 0f)
        {
            rotateSpeed = Random.Range(15f, 30f);
        }
        
        transform.Rotate(0, 0, rotateSpeed);
        
        // Faster deceleration when speed is low
        if (rotateSpeed < 1f)
        {
            rotateSpeed *= 0.95f;  // Faster deceleration
        }
        else
        {
            rotateSpeed *= 0.986f;  // Normal deceleration
        }
        
        if (rotateSpeed <= stopThreshold)
        {
            rotateSpeed = 0f;
        }
    }
}

← Back to Table of Contents