Car Control with Mouse Drag

Learn how to control a car by detecting mouse drag input in Unity. Covers Input.mousePosition, GetMouseButtonDown/Up, using transform.Translate(), and more.

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 drag
    • false: Not dragging, can start drag
  • hasDraggedOnce: Check if dragged at least once

    • true: Already dragged, no more dragging allowed
    • false: 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

  1. Screen Coordinates: Input.mousePosition uses screen coordinates, so use Camera.ScreenToWorldPoint() to convert to world coordinates
  2. Drag Distance: In pixel units, so values may vary depending on resolution
  3. Speed Conversion Ratio: Adjust the ratio to convert drag distance to speed according to your game
  4. 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;
        }
    }
}

← Back to Table of Contents