Điều khiển cảm ứng trong Unity: xử lý chạm, vuốt và kéo thả trên điện thoại

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Game di động sống nhờ cảm ứng: chạm để bắn, vuốt để đổi hướng, kéo để di chuyển. Unity cung cấp hệ thống đầu vào cho phép đọc từng ngón tay trên màn hình. Bài này hướng dẫn xử lý chạm cơ bản, nhận biết cử chỉ vuốt và kéo thả.

Hai hệ thống đầu vào của Unity

Unity có hệ thống Input cũ (lớp Input) và gói Input System mới. Dự án mới thường được khuyến nghị dùng Input System, còn nhiều hướng dẫn cũ dùng Input cũ. Để dễ hiểu khái niệm, các ví dụ dưới đây dùng lớp Input cũ; ý tưởng áp dụng tương tự ở hệ thống mới. Kiểm tra trong Project Settings xem dự án của bạn đang bật hệ thống nào, vì chỉ dùng được khi cấu hình tương ứng được bật.

Đọc một lần chạm

using UnityEngine;

public class TouchReader : MonoBehaviour
{
    void Update()
    {
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);

            switch (touch.phase)
            {
                case TouchPhase.Began:
                    Debug.Log("Bắt đầu chạm tại " + touch.position);
                    break;
                case TouchPhase.Moved:
                    Debug.Log("Đang kéo, dịch " + touch.deltaPosition);
                    break;
                case TouchPhase.Ended:
                    Debug.Log("Nhả tay");
                    break;
            }
        }
    }
}

Mỗi ngón tay có một pha: Began (vừa chạm), Moved (di chuyển), Stationary (đứng yên), Ended (nhấc lên) và Canceled (bị hệ thống hủy). Tọa độ position tính bằng điểm ảnh, gốc ở góc dưới trái màn hình.

Chuyển tọa độ màn hình sang thế giới game

Vector3 screenPos = touch.position;
Vector3 worldPos = Camera.main.ScreenToWorldPoint(
    new Vector3(screenPos.x, screenPos.y, 10f));
worldPos.z = 0f;
transform.position = worldPos;

Với camera chiếu phối cảnh, thành phần z là khoảng cách tới camera; với camera trực giao 2D, giá trị z ít quan trọng hơn nhưng vẫn nên đặt lại z cho đối tượng. Lưu ý lưu Camera.main vào biến để tránh tra cứu mỗi khung hình.

Nhận biết cú vuốt

public class SwipeDetector : MonoBehaviour
{
    private Vector2 startPos;
    [SerializeField] private float minSwipeDistance = 80f;

    void Update()
    {
        if (Input.touchCount == 0) return;
        Touch t = Input.GetTouch(0);

        if (t.phase == TouchPhase.Began)
        {
            startPos = t.position;
        }
        else if (t.phase == TouchPhase.Ended)
        {
            Vector2 delta = t.position - startPos;
            if (delta.magnitude < minSwipeDistance) return;

            if (Mathf.Abs(delta.x) > Mathf.Abs(delta.y))
                Debug.Log(delta.x > 0 ? "Vuốt phải" : "Vuốt trái");
            else
                Debug.Log(delta.y > 0 ? "Vuốt lên" : "Vuốt xuống");
        }
    }
}

Ngưỡng khoảng cách tối thiểu giúp phân biệt vuốt với chạm thường. Bạn có thể quy đổi ngưỡng theo mật độ điểm ảnh (Screen.dpi) để đồng nhất trên nhiều máy.

Kéo thả vật thể

Để kéo một đối tượng, trước hết xác định ngón tay chạm trúng đối tượng nào bằng raycast 2D:

private Transform dragged;

void Update()
{
    if (Input.touchCount == 0) return;
    Touch t = Input.GetTouch(0);
    Vector2 world = Camera.main.ScreenToWorldPoint(t.position);

    if (t.phase == TouchPhase.Began)
    {
        RaycastHit2D hit = Physics2D.Raycast(world, Vector2.zero);
        if (hit.collider != null) dragged = hit.transform;
    }
    else if (t.phase == TouchPhase.Moved && dragged != null)
    {
        dragged.position = world;
    }
    else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)
    {
        dragged = null;
    }
}

Đối tượng cần có Collider2D để raycast nhận ra.

Chạm vào giao diện

Khi dùng Canvas và Button, hãy để hệ thống EventSystem xử lý. Nếu vừa có giao diện vừa có chạm trong game, cần kiểm tra ngón tay có đang ở trên phần tử giao diện không để tránh vừa bấm nút vừa kích hoạt hành động trong game, bằng EventSystem.current.IsPointerOverGameObject(touch.fingerId).

Đa điểm chạm: thu phóng

Với hai ngón tay, tính khoảng cách giữa chúng ở khung hình trước và hiện tại; chênh lệch cho biết mức thu hay phóng. Hãy xử lý riêng từng fingerId để không nhầm khi ngón tay thay đổi thứ tự.

Mẹo thiết kế

  1. Đặt vùng điều khiển trong tầm ngón cái, tránh che nhân vật.
  2. Cho phản hồi hình ảnh hoặc rung nhẹ khi chạm.
  3. Cho phép người chơi tùy chỉnh độ nhạy.
  4. Kiểm thử trên thiết bị thật; chuột trong Editor không giống cảm ứng thật.
  5. Dùng Unity Remote hoặc bản build thử để thử nhanh.

Kết luận

Hiểu các pha chạm, chuyển tọa độ và nhận biết cử chỉ là nền tảng để làm điều khiển mượt cho game di động. Hãy bắt đầu từ một cơ chế đơn giản như kéo thả rồi nâng dần độ phức tạp.

Rung phản hồi và độ nhạy

Cảm giác điều khiển tốt đến từ chi tiết nhỏ. Thêm rung nhẹ khi trúng đích hoặc nhận sát thương giúp người chơi cảm nhận hành động. Cho phép chỉnh độ nhạy kéo và vuốt trong cài đặt, vì mỗi người cầm máy khác nhau. Đặt vùng chết nhỏ để tránh nhân vật giật khi ngón tay run nhẹ. Cuối cùng, nhờ người khác chơi thử và quan sát cách họ cầm máy; bạn sẽ thấy ngay những vị trí nút mà tay họ không với tới thoải mái.

Để học làm game hoàn chỉnh với Unity, bạn có thể tham khảo các khóa học trên codebem.com.

author_photo
Nguyễn Đình Cường

0 comment