What is Mouse Drag Control?
Mouse drag control is a feature that detects the distance and direction of mouse drag to move objects. It's used in games to control cars with swipes or drag objects to move them.
Basic Concepts
- Drag Start: Store position when mouse button is pressed
- Drag End: Store position when mouse button is released
- Drag Distance: Calculate difference between start and end positions
- Speed Conversion: Convert drag distance to movement speed
- Deceleration Effect: Gradually reduce speed to stop naturally
- State Management: Manage drag state and drag availability with flag variables
Input.mousePosition
Basic Usage
using UnityEngine;
public class MousePosition : MonoBehaviour
{
void Update()
{
// Get current mouse position (screen coordinates)
Vector3 mousePos = Input.mousePosition;
// Output X, Y coordinates
Debug.Log($"Mouse X: {mousePos.x}, Y: {mousePos.y}");
}
}
mousePosition Characteristics
- Screen Coordinates: Bottom-left is (0, 0), top-right is (Screen.width, Screen.height)
- Pixel Units: Values vary depending on screen resolution
- 2D Coordinates: Z value is always 0 (distance from camera)
Screen Coordinates Example
using UnityEngine;
public class ScreenCoordinates : MonoBehaviour
{
void Update()
{
Vector3 mousePos = Input.mousePosition;
// Screen size information
float screenWidth = Screen.width; // Screen width (pixels)
float screenHeight = Screen.height; // Screen height (pixels)
Debug.Log($"Screen size: {screenWidth} x {screenHeight}");
Debug.Log($"Mouse position: ({mousePos.x}, {mousePos.y})");
// Normalize relative to screen center (0~1)
float normalizedX = mousePos.x / screenWidth;
float normalizedY = mousePos.y / screenHeight;
Debug.Log($"Normalized position: ({normalizedX}, {normalizedY})");
}
}
Mouse Input Function Comparison
GetMouseButtonDown() - Click Start
using UnityEngine;
public class MouseDown : MonoBehaviour
{
void Update()
{
// Returns true only once when mouse button is pressed
if (Input.GetMouseButtonDown(0)) // Left button
{
Debug.Log("Mouse button pressed!");
}
}
}
Characteristics:
- Returns true only once when button is pressed
- Used to store drag start point
- Detects single input, not continuous input
GetMouseButton() - While Holding
using UnityEngine;
public class MouseButton : MonoBehaviour
{
void Update()
{
// Returns true continuously while mouse button is held
if (Input.GetMouseButton(0)) // Left button
{
Debug.Log("Mouse button is being held!");
}
}
}
Characteristics:
- Returns true continuously while button is held
- Used to check if dragging
- Detects continuous input
GetMouseButtonUp() - Click End
using UnityEngine;
public class MouseUp : MonoBehaviour
{
void Update()
{
// Returns true only once when mouse button is released
if (Input.GetMouseButtonUp(0)) // Left button
{
Debug.Log("Mouse button released!");
}
}
}
Characteristics:
- Returns true only once when button is released
- Used to store drag end point
- Detects single input
Comparison of Three Functions
using UnityEngine;
public class MouseComparison : MonoBehaviour
{
void Update()
{
// 1. Click start (once)
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Click started!");
}
// 2. While holding (continuous)
if (Input.GetMouseButton(0))
{
Debug.Log("Holding...");
}
// 3. Click end (once)
if (Input.GetMouseButtonUp(0))
{
Debug.Log("Click ended!");
}
}
}
transform.Translate() Method
Basic Usage
using UnityEngine;
public class TranslateExample : MonoBehaviour
{
void Update()
{
// Move 1 unit along X-axis
transform.Translate(1, 0, 0);
// Move 1 unit along Y-axis
transform.Translate(0, 1, 0);
// Move 1 unit along Z-axis
transform.Translate(0, 0, 1);
}
}
Translate() Parameters
transform.Translate(x, y, z);
- x: Movement distance along X-axis
- y: Movement distance along Y-axis
- z: Movement distance along Z-axis
- Note: Moves relative to local coordinate system (default)
Time-based Movement
using UnityEngine;
public class TimeBasedTranslate : MonoBehaviour
{
public float speed = 5f; // Movement distance per second
void Update()
{
// Move speed units per second along X-axis
// Multiply by Time.deltaTime to maintain constant speed regardless of framerate
transform.Translate(speed * Time.deltaTime, 0, 0);
}
}
Translate() vs Direct position Change
using UnityEngine;
public class TranslateVsPosition : MonoBehaviour
{
public float speed = 5f;
void Update()
{
// Method 1: Use Translate() (relative movement)
transform.Translate(speed * Time.deltaTime, 0, 0);
// Method 2: Direct position change (absolute position)
// transform.position = transform.position + new Vector3(speed * Time.deltaTime, 0, 0);
// Method 3: Direct position change (simple form)
// transform.position += new Vector3(speed * Time.deltaTime, 0, 0);
}
}
Differences:
- Translate(): Relative movement based on local coordinate system (useful for rotated objects)
- position: Sets absolute position based on world coordinate system
Implementing Car Control with Mouse Drag
Basic Car Controller
using UnityEngine;
public class CarController : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false; // Flag to check if currently dragging
void Update()
{
// Store start position when mouse button is pressed
if (Input.GetMouseButtonDown(0) && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // Start dragging
}
// Store end position and calculate speed when mouse button is released
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
// Calculate drag distance (X-axis based)
float dragGap = endPosition.x - startPosition.x;
// Convert drag distance to speed
carSpeed = dragGap * 0.001f;
isDragging = false; // End dragging
}
// Move car
transform.Translate(carSpeed, 0, 0);
// Deceleration handling
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
else
{
carSpeed *= 0.98f; // Decrease by 2% each frame
}
}
}
Complete Car Controller Example
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Controller class for controlling car with mouse drag
/// Car speed is determined by the distance of mouse drag.
/// Can only drag once, and new drag is only possible when the car is completely stopped.
/// </summary>
public class CarController2 : MonoBehaviour
{
/// <summary>
/// Current movement speed of the car
/// Positive value moves right, negative value moves left.
/// </summary>
public float carSpeed = 0f;
/// <summary>
/// Mouse drag start position
/// Stored in GetMouseButtonDown(), used in GetMouseButtonUp().
/// </summary>
Vector2 startPosition;
/// <summary>
/// Flag to check if currently dragging
/// true means currently dragging, false means not dragging
/// </summary>
bool isDragging = false;
/// <summary>
/// Flag to check if drag has occurred at least once
/// true means already dragged, so no more dragging allowed
/// </summary>
bool hasDraggedOnce = false;
void Start()
{
// Initialization (currently unused but can add initial settings here)
}
void Update()
{
// Unity mouse input function reference
// GetMouseButton(0): Returns true while mouse button is held (continuous input detection)
// GetMouseButtonDown(0): Returns true only once when mouse button is pressed (single input detection)
// GetMouseButtonUp(0): Returns true only once when mouse button is released (single input detection)
// New drag can only start when: never dragged && not dragging && car completely stopped
// Condition: !hasDraggedOnce (not dragged yet) && !isDragging (not dragging) && carSpeed == 0f (completely stopped)
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // Set drag start flag
}
// Only process drag end when dragging
if (Input.GetMouseButtonUp(0) && isDragging)
{
// Drag end position
Vector2 endPosition = Input.mousePosition;
// Calculate drag distance (X-axis based)
// Positive value means drag right, negative value means drag left
float dragGap = endPosition.x - startPosition.x;
// Convert drag distance to speed
// 0.005f is the ratio to convert drag distance to speed
// 0.23f is additional damping coefficient (speed adjustment)
carSpeed = (dragGap * 0.005f) * 0.23f;
isDragging = false; // Clear drag end flag
hasDraggedOnce = true; // Mark that drag has occurred once (no more dragging allowed)
}
// Move car by current speed along X-axis
// Translate(x, y, z): Moves relative to local coordinate system
transform.Translate(carSpeed, 0, 0);
// Deceleration handling
// Stop completely when speed reaches almost 0
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
else
{
// Reduce speed to 98% each frame (2% decrease)
// Creates natural deceleration effect.
carSpeed *= 0.98f;
}
}
}
Calculating Drag Distance
Basic Drag Distance Calculation
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;
// Calculate drag distance
float distance = endPos.x - startPos.x;
Debug.Log($"Drag distance: {distance} pixels");
}
}
}
Bidirectional Drag Handling
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("Dragged right!");
}
else if (dragGap < 0)
{
Debug.Log("Dragged left!");
}
else
{
Debug.Log("No drag (click only)");
}
}
}
}
2D Drag Distance Calculation
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-axis distance
float distanceX = endPos.x - startPos.x;
// Y-axis distance
float distanceY = endPos.y - startPos.y;
// Total distance (Pythagorean theorem)
float totalDistance = Mathf.Sqrt(distanceX * distanceX + distanceY * distanceY);
Debug.Log($"X distance: {distanceX}, Y distance: {distanceY}, Total distance: {totalDistance}");
}
}
}
Speed Conversion
Converting Drag Distance to Speed
using UnityEngine;
public class DragToSpeed : MonoBehaviour
{
public float speedMultiplier = 0.001f; // Speed conversion ratio
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;
// Convert drag distance to speed
carSpeed = dragGap * speedMultiplier;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
Speed Limiting
using UnityEngine;
public class SpeedLimit : MonoBehaviour
{
public float maxSpeed = 10f; // Maximum speed
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;
// Apply speed limit
carSpeed = Mathf.Clamp(newSpeed, -maxSpeed, maxSpeed);
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
State Management
Managing Drag State with Flag Variables
using UnityEngine;
public class DragStateManagement : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false; // Check if currently dragging
bool hasDraggedOnce = false; // Check if dragged at least once
void Update()
{
// Condition: not dragged yet && not dragging && completely stopped
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true; // Start dragging
}
// Only process end when dragging
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
float dragGap = endPosition.x - startPosition.x;
carSpeed = dragGap * 0.001f;
isDragging = false; // End dragging
hasDraggedOnce = true; // Mark that drag occurred once
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
}
}
Role of Flag Variables
-
isDragging: Check if currently dragging
true: Dragging, cannot start new dragfalse: Not dragging, can start drag
-
hasDraggedOnce: Check if dragged at least once
true: Already dragged, no more dragging allowedfalse: Not dragged yet, can drag
Practical Usage Examples
Example 1: Car That Can Only Drag Once
using UnityEngine;
public class OneTimeDrag : MonoBehaviour
{
public float carSpeed = 0f;
Vector2 startPosition;
bool isDragging = false;
bool hasDraggedOnce = false; // Can only drag once
void Update()
{
// Can only start drag when: never dragged && not dragging && stopped
if (Input.GetMouseButtonDown(0) && !hasDraggedOnce && !isDragging && carSpeed == 0f)
{
startPosition = Input.mousePosition;
isDragging = true;
}
// Only process end when dragging
if (Input.GetMouseButtonUp(0) && isDragging)
{
Vector2 endPosition = Input.mousePosition;
float dragGap = endPosition.x - startPosition.x;
carSpeed = dragGap * 0.001f;
isDragging = false;
hasDraggedOnce = true; // Already dragged once, no more allowed
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (carSpeed <= 0.005f)
{
carSpeed = 0f;
}
}
}
Example 2: Setting Minimum Drag Distance
using UnityEngine;
public class MinDragDistance : MonoBehaviour
{
public float minDragDistance = 50f; // Minimum drag distance (pixels)
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;
// Check minimum drag distance
if (Mathf.Abs(dragGap) >= minDragDistance)
{
carSpeed = dragGap * 0.001f;
}
else
{
// Ignore if below minimum distance (treat as click)
carSpeed = 0f;
}
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
Example 2: Displaying Drag Direction
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;
// Display drag direction
if (dragGap > 0)
{
Debug.Log("→ Dragged right!");
}
else if (dragGap < 0)
{
Debug.Log("← Dragged left!");
}
carSpeed = dragGap * 0.001f;
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
Example 3: Adjusting Acceleration Based on Drag Speed
using UnityEngine;
public class VariableAcceleration : MonoBehaviour
{
public float carSpeed = 0f;
public float fastDragMultiplier = 0.002f; // Fast drag multiplier
public float slowDragMultiplier = 0.0005f; // Slow drag multiplier
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);
// Select multiplier based on drag speed
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;
}
}
}
Example 4: Jump with Y-axis Drag
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-axis drag
// Jump when dragging up
if (dragGap > 0)
{
jumpSpeed = dragGap * 0.01f;
}
}
// Move along Y-axis (jump)
transform.Translate(0, jumpSpeed, 0);
jumpSpeed *= 0.95f;
// Gravity effect (fall down)
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;
}
}
}
Notes
- Screen Coordinates:
Input.mousePositionuses screen coordinates, so useCamera.ScreenToWorldPoint()to convert to world coordinates - Drag Distance: In pixel units, so values may vary depending on resolution
- Speed Conversion Ratio: Adjust the ratio to convert drag distance to speed according to your game
- Negative Speed: Dragging left produces negative values, so use
Mathf.Abs()to compare absolute values if needed
Practical Tips
Tip 1: Adjust Speed in Inspector
using UnityEngine;
public class InspectorCarControl : MonoBehaviour
{
[Header("Speed Settings")]
public float carSpeed = 0f;
[Header("Drag Conversion Ratio")]
public float dragToSpeedRatio = 0.001f;
public float speedDamping = 0.23f;
[Header("Deceleration Settings")]
[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;
}
}
}
Tip 2: Visual Feedback During Drag
using UnityEngine;
public class DragFeedback : MonoBehaviour
{
public float carSpeed = 0f;
public LineRenderer dragLine; // For displaying drag line
Vector2 startPos;
bool isDragging = false;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
isDragging = true;
// Start drag line
if (dragLine != null)
{
dragLine.enabled = true;
}
}
// Update line while dragging
if (isDragging && Input.GetMouseButton(0))
{
Vector2 currentPos = Input.mousePosition;
// Drag line display logic...
}
if (Input.GetMouseButtonUp(0))
{
Vector2 endPos = Input.mousePosition;
float dragGap = endPos.x - startPos.x;
carSpeed = dragGap * 0.001f;
isDragging = false;
// Hide drag line
if (dragLine != null)
{
dragLine.enabled = false;
}
}
transform.Translate(carSpeed, 0, 0);
carSpeed *= 0.98f;
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}
Tip 3: Smooth Deceleration
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);
// Faster deceleration when speed is low
if (Mathf.Abs(carSpeed) < 1f)
{
carSpeed *= 0.95f; // Faster deceleration
}
else
{
carSpeed *= 0.98f; // Normal deceleration
}
if (Mathf.Abs(carSpeed) <= 0.005f)
{
carSpeed = 0f;
}
}
}