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
- Framerate Independence: Without using
Time.deltaTime, rotation speed may vary depending on framerate - Stop Condition: Use thresholds like
rotateSpeed <= 0.05fto create smooth stop effects - State Check: Must check conditions to prevent starting new rotation while already rotating
- 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;
}
}
}