Search…

Hiện Thực Menu Select Level với Scroll Rect

29/09/20206 min read
Hiện thực level select với thành phần Scroll Rect trong Unity.

Các thể loại game giải đố (puzzle), luôn có 1 hệ thống màn chơi đa dạng với các cấp độ từ dễ đến khó để thử thách người chơi. Do đó cần 1 nơi để hiển thị các cấp độ chơi này 1 cách trực quan sinh động và hấp dẫn.

Đối với Unity, việc này được hỗ trợ 1 phần bởi thành phần Scroll Rect.

Bài viết hướng dẫn cách sử dụng Scroll Rect để tạo ra 1 menu quản lý cấp độ chơi (level select) cùng với các hiệu ứng đẹp mắt.

Thành phần Scroll Rect

Scroll Rect trong Unity là 1 thành phần UI, do đó chỉ có thể thêm Scroll Rect vào 1 đối tượng UI. Để thêm thành phần Scroll Rect, chọn Add Component → UI Scroll Rect. Giao diện của Scroll Rect trong cửa sổ Inspector như sau:

 

Scroll rect trong Unity.

Tuỳ chỉnh tại Inspector

Content

Thuộc tính này tham chiếu đến thành phần Rect Transform của 1 đối tượng UI. Đối tượng này được Scroll Rect quản lý và chuyển động theo các thuộc tính chức năng của Scroll Rect.

Horizontal - Vertical

2 checkbox quy định hướng mà đối tượng có thể được scroll, khi bỏ đánh dấu checkbox nào thì đối tượng sẽ không thể scroll theo hướng tương ứng.

  • Horizontal tương đương với khả năng cuộn theo chiều ngang của đối tượng.
  • Vertical tương đương với khả năng cuộn theo chiều dọc của đối tượng.

Scrollbar

2 tuỳ chọn Scrollbar cho phép Scroll Rect tham chiếu tới các đối tượng UI Scrollbar để hiển thị thanh cuộn, nếu không cần thiết hiển thị Scrollbar có thể bỏ qua 2 tuỳ chọn này.

Movement Type

Đây là các kiểu di chuyển của đối tượng được quản lý bởi Content. Unity hỗ trợ ba kiểu chuyển động cho Scroll Rect:

  • Unrestricted: đối tượng Content sẽ không bị giới hạn bởi kích thước Rect Transform của đối tượng quản lý Scroll Rect. Nói cách khác, khi click chuột di chuyển đối tượng, đối tượng đó sẽ có thể di chuyển tự do ra ngoài đối tượng quản lý.
  • Elastic: đối tượng Content bị giới hạn bởi kích thước Rect Transform của đối tượng quản lý. Ở tuỳ chọn này, đối tượng Content có thể di chuyển 1 phần ra khỏi đối tượng quản lý khi ta giữ nguyên sự kiện Input (như click chuột, touch, ...) và di chuyển ra ngoài giới hạn của đối tượng quản lý, tuy nhiên ngay khi sự kiện Input kết thúc, đối tượng Content sẽ di chuyển lại vào giới hạn với hiệu ứng built-in đẹp mắt (bounce), mức độ bounce của đối tượng được quản lý ở thuộc tính Elasticity.
  • Clamped: tương tự tuỳ chọn Elastic, đối tượng sẽ không thể đi ra khỏi giới hạn. Khi chạm đến giới hạn, đối tượng đơn giản sẽ dừng lại và không thể di chuyển vượt quá giới hạn của đối tượng quản lý.

Với các nhu cầu thông thường thì tuỳ chọn Elastic là khá phù hợp và đẹp mắt.

Inertia

Tuỳ chọn này hỗ trợ tính chất vật lý trong chuyển động của đối tượng. Khi được kích hoạt và sự kiện Input kết thúc, đối tượng vẫn sẽ được scroll với vận tốc giảm dần. Vận tốc ban đầu của đối tượng dựa vào khoảng cách giữa 2 lần nhận được input và được tính toán 1 cách tự động.

Thuộc tính Deceleration Rate chính là độ giảm vận tốc của đối tượng, giá trị càng lớn thì đối tượng sẽ dừng lại càng nhanh và ngược lại. Tuỳ chọn này chỉ hiện ra khi Inertia được kích hoạt.

Event OnValueChange

Event này sẽ được gọi khi vị trí của Scroll Rect được thay đổi, vị trí hiện tại sẽ được trả về dưới dạng 1 Vector2, cách sử dụng event tương tự như event OnClick của UI Button.

Thao tác với C# Script

OnDrag

Các hàm được override và tự động gọi mỗi khi nhận được sự kiện trên Scroll Rect, các hàm nhận sự kiện Drag có nguyên mẫu như sau:

public void OnDrag(EventSystems.PointerEventData eventData);
public void OnBeginDrag(EventSystems.PointerEventData eventData);
public void OnEndDrag(EventSystems.PointerEventData eventData);

Mỗi hàm đều có 1 chức năng cụ thể, không cần quan tâm đến giá trị truyền vào hàm. Trong quá trình làm việc thực tế thì thường bỏ qua 2 hàm này và sử dụng sự kiện Input thay thế.

Ngoài ra, các thuộc tính hiển thị ở Inspector cũng có thể được tuỳ chỉnh trong script.

My Scroll Rect

Nếu đã từng chơi game Angry Bird (Rovio) sẽ thấy menu Level Select được thể hiện dưới dạng các trang liên tiếp theo chiều ngang. Khi kéo sang trái hoặc phải, menu sẽ dịch chuyển qua 1 trang level với hiệu ứng rất hợp lý, từ Angry Bird có thể hiện thực lại menu Level Select như sau:

  • Menu Level Select là 1 đối tượng UI Image với color trong suốt hoàn toàn. Các level được thêm vào thủ công hoăc tự động và được chia thành nhiều trang. Chi tiết cách hiện thực sẽ hướng dẫn trong 1 bài viết khác, hoặc có thể tham khảo thêm ở phần demo.
  • Thành phần Scroll Rect được gắn vào 1 Canvas với Content là menu Level Select. Các thông số được thiết lập như hình dưới.
My scroll rect Unity.
  • Ngoài ra, hiện thực 1 C# Script giúp kiểm tra và cập nhật trạng thái cho menu, các hiệu ứng và logic chuyển động cũng được tích hợp và xử lý trong script, nội dung của script như sau:
using UnityEngine;
using UnityEngine.UI;

public class ScrollRectController : MonoBehaviour
{
	private ScrollRect m_scrollPanel;

	public int m_pages;
	private int m_currentPage;
	private Vector2[] m_currentPagePosition;

	private float m_dragTime;
	private float m_lastTime;

	private Vector3 m_savePosition;
	private Vector3 m_startPosition;

	void Start()
	{
		m_scrollPanel = GetComponent<ScrollRect>();

		m_currentPage = 1;
		m_currentPagePosition = new Vector2[m_pages];

		for (int i = m_pages - 1; i >= 0; i--)
			m_currentPagePosition[m_pages - 1 - i] = new Vector2(
				Screen.width / 2 * (m_pages - 1) - Screen.width * (m_pages - i - 1),
				m_scrollPanel.content.anchoredPosition.y);

		m_dragTime = 1f;
	}


	void Update()
	{
		if (Input.GetMouseButtonDown(0))
		{
			m_savePosition = m_startPosition = Input.mousePosition;
			m_lastTime = Time.time;
		}

		if (Input.GetMouseButton(0))
			Dragging();
		else
		{
			if (Input.GetMouseButtonUp(0))
			{	
				Dropping();
			}
			
			Vector2 temp = 
				Vector2.Lerp(m_scrollPanel.content.anchoredPosition, 
								m_currentPagePosition[m_currentPage - 1], 
								5f * Time.deltaTime);
			m_scrollPanel.content.anchoredPosition = temp;
		}
	}

	void Dragging()
	{
		if (Time.time - m_lastTime >= m_dragTime)
		{
			m_savePosition = Input.mousePosition;
			m_lastTime = Time.time;
		}
	}

	void Dropping()
	{
		if (Input.mousePosition.x - m_savePosition.x >= 50f || Input.mousePosition.x - m_startPosition.x >= Screen.width / 2)
		{
			if (m_currentPage > 1)
				m_currentPage--;
		}
		else if (m_savePosition.x - Input.mousePosition.x >= 50f || m_startPosition.x - Input.mousePosition.x >= Screen.width / 2)
		{
			if (m_currentPage < m_pages)
				m_currentPage++;
		}
	}
}

Dòng 6 – 16 là tất cả những thuộc tính cần thiết để thao tác với Scroll Rect cũng như quản lý vị trí, ... thuộc tính m_pages có phạm vi là public để lập trình viên có thể tự do tạo ra nhiều trang level và tuỳ chỉnh dễ dàng trong Unity.

Tại hàm Start, thiết lập giá trị ban đầu cho các thuộc tính.

Hàm Update chính là luồng sự kiện và logic của Scroll Rect, khi nhận sự kiện click chuột (hoặc touch trên smartphone), đối tượng Content sẽ di chuyển theo input do thành phần Scroll Rect quản lý. Khi bỏ click chuột (hoặc touch), script sẽ cập nhật lại trang hiện tại và di chuyển menu về trang đó.

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024