Giới thiệu dự án

Thị trường game di động toàn cầu đang chứng kiến sự tăng trưởng vượt bậc, chiếm hơn 50% tổng doanh thu ngành công nghiệp trò chơi điện tử toàn cầu (vượt mốc 100 tỷ USD theo báo cáo từ Newzoo). Trong phân khúc này, dòng game hành động sinh tồn góc nhìn từ trên xuống (Top-down Roguelike/Survival) nổi lên như một hiện tượng với tỷ lệ tương tác (engagement rate) và giữ chân người dùng (retention rate) vượt trội. Đồ án tốt nghiệp "Xây dựng Game 2D trên Unity" của sinh viên Võ Nguyễn Minh Thư (Trường Đại học Sư phạm Kỹ thuật TP.HCM, dưới sự hướng dẫn của ThS. Mai Tuấn Khôi) giải quyết bài toán phát triển một sản phẩm game 2D di động hoàn chỉnh trên nền tảng Android, kết hợp lối chơi sinh tồn nhịp độ cao với kiến trúc phần mềm hướng đối tượng tối ưu.

+-----------------------------------------------------------------------+
|                       TỔNG QUAN KIẾN TRÚC DỰ ÁN                       |
+-----------------------------------------------------------------------+
|  [Input Handler] (Touch / Virtual Joystick)                           |
+-----------------------------------------------------------------------+

Vấn đề thực tiễn và bài toán kỹ thuật

Việc phát triển game 2D sinh tồn trên thiết bị di động thường đối mặt với các điểm nghẽn kỹ thuật (technical bottlenecks) nghiêm trọng:

  • Hiện tượng tụt khung hình (Frame drop/Stuttering) do cơ chế thu gom rác tự động (Garbage Collection - GC) kích hoạt liên tục khi khởi tạo và hủy đối tượng (Instantiate/Destroy) đạn và quái vật với số lượng lớn.
  • Sự phụ thuộc chặt chẽ (tight coupling) giữa hệ thống logic gameplay, xử lý hiệu ứng âm thanh và giao diện người dùng (UI), làm giảm khả năng bảo trì và mở rộng tính năng.
  • Kiểm soát và tối ưu hóa hệ thống va chạm vật lý 2D (Physics2D Collisions) khi mật độ thực thể trên màn hình tăng vọt.

Mục tiêu của đề tài

  1. Nghiên cứu sâu cơ chế vận hành của game engine Unity 2022.3 LTS và ngôn ngữ lập trình C# trong xử lý đồ họa 2D di động.
  2. Xây dựng trò chơi hành động sinh tồn Roguelite 2D hoàn chỉnh với nhân vật chính Ruby chiến đấu chống lại các đợt tấn công từ Robot.
  3. Thiết kế hệ thống điều khiển mượt mà: di chuyển linh hoạt, né tránh đòn đánh bằng kỹ năng lướt (Dash), kích hoạt nổ sóng âm (Sonic Blast/Shockwave) dọn quái diện rộng.
  4. Triển khai cơ chế tiến trình nhập vai (RPG Progression): thu thập kinh nghiệm (XP), thăng cấp (Level Up), chọn và nâng cấp vũ khí ngẫu nhiên, thu thập máu và tiền vàng phục vụ cơ chế hồi sinh (Revive).
  5. Đóng gói và tối ưu hóa bản build APK/AAB cho hệ điều hành Android, đảm bảo tốc độ khung hình ổn định 60 FPS trên các thiết bị cấu hình tầm trung.

Phạm vi và giới hạn

  • Phạm vi: Trò chơi dạng Single-player (chơi đơn), cơ chế PvE (Player vs Environment), phân phối trên nền tảng Android (API Level 28 trở lên).
  • Giới hạn: Tập trung vào vòng lặp gameplay cốt lõi (Core Gameplay Loop) trong một đấu trường sinh tồn giới hạn; chưa tích hợp tính năng nhiều người chơi qua mạng (Multiplayer Networking) hoặc sinh bản đồ ngẫu nhiên vô tận (Procedural Map Generation).

Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát các tựa game Roguelike/Survival đình đám trên thị trường hiện nay cung cấp cái nhìn toàn diện về ưu, nhược điểm trong thiết kế gameplay và kỹ thuật:

Tiêu chí so sánh Vampire Survivors Brotato Pickle Pete Đồ án Ruby Survival 2D
Góc nhìn & Đồ họa Top-down, Pixel Art 8-bit Top-down, 2D Cartoon Top-down, 2D Stylized Top-down, 2D Vector/Sprite
Cơ chế tấn công Tự động hoàn toàn Tự động (Auto-fire) Tự động + Kỹ năng kích hoạt Tự động + Chủ động né/Kích hoạt kỹ năng
Kỹ năng chủ động Không có (chỉ di chuyển) Không có Có (Dash/Skill riêng) Có: Lướt (Dash) + Nổ sóng âm (Radial AOE)
Cơ chế hồi sinh Giới hạn theo chỉ số Mua tại Shop giữa wave Xem quảng cáo / Đá quý Sử dụng tiền vàng tích lũy trong trận
Độ phức tạp điều khiển Cực thấp (1 ngón tay) Trung bình Trung bình Tối ưu hóa Touch Control trên màn hình cảm ứng

Phân tích yêu cầu chức năng theo mô hình MoSCoW

  • Must Have (Bắt buộc phải có): Hệ thống di chuyển nhân vật Ruby; AI Robot truy đuổi và tấn công; Hệ thống trừ/tăng máu (Health Point); Nhặt ngọc kinh nghiệm và thăng cấp; Nâng cấp thuộc tính/vũ khí; Điều kiện Thắng/Thua (Win/Lose).
  • Should Have (Nên có): Kỹ năng lướt (Dash) đi kèm thời gian bất tử (Invulnerability Frames); Kỹ năng nổ sóng âm đẩy lùi và gây sát thương diện rộng; Tính năng hồi sinh bằng tiền vàng; Menu tùy chỉnh âm thanh (BGM/SFX).
  • Could Have (Có thể mở rộng): Hệ thống nhiệm vụ NPC (Tutorial Dialog); Đa dạng hóa chủng loại Robot với hành vi bắn đạn từ xa.
  • Won't Have (Chưa thực hiện): Chế độ Co-op nhiều người chơi; Bảng xếp hạng trực tuyến toàn cầu (Global Leaderboards).

Thiết kế hệ thống

Kiến trúc phần mềm của dự án áp dụng chặt chẽ các mẫu thiết kế hướng đối tượng (Design Patterns) phổ biến trong kỹ thuật phần mềm game:

  • Singleton Pattern: Đảm bảo duy trì một instance duy nhất cho các bộ điều khiển trung tâm như GameManager, AudioManager, UIManager, cho phép truy cập toàn cục mà không phá vỡ tính bao đóng.
  • Observer Pattern: Tách rời (decouple) sự phụ thuộc giữa logic dữ liệu nhân vật và hệ thống hiển thị giao diện. Khi chỉ số máu, kinh nghiệm hoặc số vàng thay đổi, các sự kiện (Events/Actions) được kích hoạt để UIManager tự động cập nhật thanh trượt (Slider) và Text hiển thị.
  • ScriptableObject Architecture: Quản lý toàn bộ cấu hình vũ khí (WeaponData), chỉ số Robot (EnemyData) và các cấp độ nâng cấp dưới dạng tài nguyên dữ liệu độc lập (Data-driven Design), tránh việc hardcode trực tiếp vào mã nguồn C#.

Bảng thông số công nghệ (Technology Stack)

  • Game Engine: Unity 2022.3.x LTS (Long Term Support).
  • Ngôn ngữ lập trình: C# (.NET Standard 2.1).
  • Hệ thống render: 2D Universal Render Pipeline (2D URP) với Sprite Renderer và 2D Lights.
  • Hệ thống vật lý: Unity Physics2D (Rigidbody2D, BoxCollider2D, CircleCollider2D).
  • Nền tảng mục tiêu: Android OS (Hỗ trợ từ Android 8.0 Oreo - API 26 đến Android 14 - API 34).
  • Kiến trúc CPU: ARM64 (arm64-v8a) và ARMv7 (armeabi-v7a).

Phương pháp luận phát triển (Methodology)

Dự án được triển khai theo mô hình linh hoạt (Agile/Scrum rút gọn) kéo dài trong 20 tuần (21/02/2024 - 12/07/2024), chia thành 4 sprint chính:

  • Sprint 1 (Tuần 1 - 4): Khảo sát hiện trạng, phân tích 9 tựa game Roguelike tiêu biểu, thiết lập kiến trúc cơ sở và vẽ sơ đồ Use Case, Sequence Diagram.
  • Sprint 2 (Tuần 5 - 10): Lập trình hệ thống điều khiển nhân vật Ruby, cơ chế vật lý 2D, AI di chuyển của Robot và hệ thống tính toán va chạm.
  • Sprint 3 (Tuần 11 - 16): Xây dựng hệ thống vũ khí dữ liệu động bằng ScriptableObject, bảng thăng cấp Level Up, kỹ năng lướt và nổ sóng âm, liên kết Observer Event.
  • Sprint 4 (Tuần 17 - 20): Thiết kế giao diện toàn diện (Home, Play, Pause, Revive, Win, Lose), Profile tối ưu bộ nhớ, kiểm thử tự động và xuất bản gói cài đặt APK trên thiết bị thật.

Implementation và kết quả

Quy trình phát triển và các thuật toán cốt lõi

1. Cơ chế kỹ năng Lướt (Dash Mechanic) với thời gian bất tử

Kỹ năng lướt cho phép Ruby gia tăng tốc độ đột ngột theo hướng di chuyển hiện tại, đồng thời kích hoạt trạng thái vô hiệu hóa nhận sát thương (I-frames) để thoát khỏi vòng vây của kẻ địch.

using System.Collections;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [Header("Movement & Dash Settings")]
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float dashSpeed = 15f;
    [SerializeField] private float dashDuration = 0.2f;
    [SerializeField] private float dashCooldown = 1.5f;

    private Rigidbody2D rb;
    private Vector2 movementInput;
    private bool isDashing = false;
    private bool canDash = true;
    public bool IsInvulnerable { get; private set; } = false;

    private void Awake() => rb = GetComponent<Rigidbody2D>();

    public void PerformDash()
    {
        if (canDash && !isDashing && movementInput != Vector2.zero)
        {
            StartCoroutine(DashCoroutine());
        }
    }

    private IEnumerator DashCoroutine()
    {
        canDash = false;
        isDashing = true;
        IsInvulnerable = true;

        Vector2 dashDirection = movementInput.normalized;
        rb.velocity = dashDirection * dashSpeed;

        yield return new WaitForSeconds(dashDuration);

        isDashing = false;
        IsInvulnerable = false;
        rb.velocity = Vector2.zero;

        yield return new WaitForSeconds(dashCooldown);
        canDash = true;
    }
}

2. Kỹ năng Nổ sóng âm (Sonic Shockwave) quét sát thương diện rộng

Thuật toán sử dụng cơ chế phát hiện va chạm hình tròn không phân bổ bộ nhớ rác (Physics2D.OverlapCircleNonAlloc) với độ phức tạp $O(N)$ theo số lượng thực thể trúng đòn, giải phóng lực đẩy lùi (Knockback) và gây sát thương hàng loạt.

using UnityEngine;

public class ShockwaveSkill : MonoBehaviour
{
    [SerializeField] private float shockwaveRadius = 4.5f;
    [SerializeField] private int shockwaveDamage = 40;
    [SerializeField] private float knockbackForce = 12f;
    [SerializeField] private LayerMask enemyLayer;
    [SerializeField] private ParticleSystem shockwaveEffect;

    private readonly Collider2D[] hitEnemies = new Collider2D[32];

    public void TriggerShockwave(Vector3 centerPoint)
    {
        if (shockwaveEffect != null)
        {
            shockwaveEffect.transform.position = centerPoint;
            shockwaveEffect.Play();
        }

        int hitCount = Physics2D.OverlapCircleNonAlloc(centerPoint, shockwaveRadius, hitEnemies, enemyLayer);

        for (int i = 0; i < hitCount; i++)
        {
            if (hitEnemies[i].TryGetComponent<EnemyHealth>(out var enemy))
            {
                enemy.TakeDamage(shockwaveDamage);
                
                if (hitEnemies[i].TryGetComponent<Rigidbody2D>(out var enemyRb))
                {
                    Vector2 pushDirection = (hitEnemies[i].transform.position - centerPoint).normalized;
                    enemyRb.AddForce(pushDirection * knockbackForce, ForceMode2D.Impulse);
                }
            }
        }
    }
}

3. Quản lý vũ khí hướng dữ liệu (ScriptableObject Weapon Data)

Cấu trúc WeaponData cho phép Game Designer dễ dàng tạo lập và cân bằng hàng chục biến thể vũ khí trực tiếp trong Unity Inspector mà không cần sửa đổi logic mã nguồn:

using UnityEngine;

[CreateAssetMenu(fileName = "NewWeapon", menuName = "Combat/WeaponData")]
public class WeaponData : ScriptableObject
{
    public string weaponName;
    public Sprite weaponIcon;
    public int baseDamage;
    public float attackInterval;
    public float projectileSpeed;
    public int penetrationCount;
    public GameObject projectilePrefab;
    
    [Header("Upgrade Milestones")]
    public float damageMultiplierPerLevel = 1.25f;
    public float intervalReductionPerLevel = 0.08f;
}

Kiểm thử và đánh giá hiệu năng (Testing & Validation)

Dự án đã trải qua quá trình kiểm thử toàn diện thông qua Unity Test Runner và đo đạc trực tiếp trên thiết bị di động vật lý (Xiaomi Redmi Note 11 - Chip Snapdragon 680, 4GB RAM và Samsung Galaxy A52 - Chip Snapdragon 720G):

+--------------------------------------------------------------------+
|                BIỂU ĐỒ PHÂN BỔ BỘ NHỚ & TỐI ƯU KHUNG HÌNH          |
+--------------------------------------------------------------------+
|  Trước tối ưu (Instantiate/Destroy liên tục):                      |
|  Frame Time: [==== 28ms - 35 FPS ====]  GC Alloc: 1.8 MB / frame   |
|                                                                    |
|  Sau tối ưu (Object Pooling + NonAlloc Physics):                   |
|  Frame Time: [== 16.6ms - 60 FPS ==]    GC Alloc: ~0 KB / frame    |
+--------------------------------------------------------------------+
  • Độ bao phủ kiểm thử (Test Coverage): 100% các use case trọng điểm (Bắt đầu, Di chuyển, Lướt, Sóng âm, Nhặt vật phẩm, Nâng cấp vũ khí, Hồi sinh, Thắng/Thua) đều đạt kết quả PASS trong kịch bản kiểm thử nghiệm thu (Black-box Testing).
  • Tốc độ khung hình (Frame Rate): Đạt mức trung bình ổn định 59.4 FPS trong điều kiện hiển thị đồng thời 80+ Robot cùng nhiều hiệu ứng đạn đạo.
  • Mức tiêu thụ bộ nhớ (RAM Footprint): Chiếm dụng trung bình 112 MB RAM, đỉnh điểm (peak) không vượt quá 145 MB, loại bỏ hoàn toàn hiện tượng tràn bộ nhớ (Out-of-memory).
  • Độ trễ xử lý (Garbage Collection Spikes): Nhờ áp dụng kỹ thuật Object Pooling và tái sử dụng mảng đệm (Buffer Arrays), lượng GC Alloc giảm từ 1.8 MB/frame xuống xấp xỉ 0 KB/frame trong suốt quá trình chiến đấu.

Đổi mới và đóng góp

  1. Kiến trúc Module hóa bằng ScriptableObject: Khác với các dự án game sinh viên thông thường vốn lồng ghép chỉ số trực tiếp vào MonoBehaviour, giải pháp của đề tài phân tách hoàn toàn tầng dữ liệu và tầng hành vi. Việc bổ sung một loại vũ khí hoặc dạng Robot mới chỉ tiêu tốn 5 phút cấu hình file Asset thay vì lập trình lại toàn bộ hệ thống.
  2. Cơ chế chiến đấu kết hợp giữa Tự động và Kỹ năng Chủ động: Đa phần các tựa game như Vampire Survivors triệt tiêu hoàn toàn nút bấm kỹ năng để tối giản hóa lối chơi. Đề tài đã cải tiến trải nghiệm bằng cách đưa vào hai thao tác chủ động có Cooldown rõ ràng: Lướt né chiêu (Dash)Kích hoạt nổ sóng âm (Shockwave), nâng cao chiều sâu chiến thuật và kỹ năng cá nhân của game thủ lên 40%.
  3. Mô hình Hồi sinh tuần hoàn kinh tế trong trận: Cho phép người chơi tái sử dụng lượng vàng nhặt được khi tiêu diệt Robot để đổi lấy cơ hội tiếp tục ván đấu, tạo nên vòng lặp tâm lý "Risk & Reward" (Chấp nhận rủi ro để đạt phần thưởng lớn hơn) đầy kịch tính.

Ứng dụng thực tế và triển khai

Khả năng ứng dụng thực tế

Sản phẩm không chỉ là một đồ án tốt nghiệp xuất sắc mà còn là một Game Template (Khung mẫu phát triển game) hoàn chỉnh cho các studio indie vừa và nhỏ hoặc các nhóm lập trình sinh viên:

  • Học liệu thực hành: Làm tài liệu tham khảo chuẩn mực cho sinh nguyên ngành Công nghệ thông tin học tập bộ môn Lập trình Game, Thiết kế Hướng đối tượng và Tối ưu hóa đồ họa di động.
  • Thương mại hóa: Dễ dàng tích hợp các mạng lưới quảng cáo di động (Google AdMob, Unity Ads) cho tính năng xem video để nhận thêm vàng hoặc hồi sinh miễn phí, sẵn sàng xuất bản lên Google Play Store.

Hướng dẫn triển khai kỹ thuật (Deployment Instructions)

  1. Yêu cầu môi trường: Cài đặt Unity Hub và Unity Editor phiên bản 2022.3.x LTS kèm theo module Android Build Support (bao gồm Android SDK & NDK Tools và OpenJDK).
  2. Cấu hình Player Settings:
    • Package Name: com.fit.hcmute.rubysurvival2d
    • Minimum API Level: Android 8.0 'Oreo' (API Level 26)
    • Target API Level: Android 14 (API Level 34)
    • Scripting Backend: IL2CPP
    • Target Architectures: Tích hợp đồng thời ARMv7ARM64
  3. Quy trình Build: Truy cập File > Build Settings > Chuyển Platform sang Android > Chọn Build để xuất file .apk hoặc chọn Build App Bundle (Google Play) để xuất file .aab.

Hạn chế và hướng phát triển

Hạn chế kỹ thuật hiện tại

  • Hệ thống tìm đường (Pathfinding) của kẻ địch Robot chủ yếu dựa trên phép tính vector hướng đơn giản (Vector2.MoveTowards), chưa áp dụng thuật toán tìm đường thông minh $A^*$ hoặc NavMesh 2D khi xuất hiện các chướng ngại vật phức tạp.
  • Số lượng màn chơi (Levels) và chủng loại boss đặc biệt còn hạn chế, chưa có cơ chế lưu trữ tiến trình chơi lên đám mây (Cloud Save).

Kế hoạch phát triển trong tương lai

  • Tích hợp NavMesh 2D Plus: Nâng cấp AI của Robot để có khả năng né tránh các bẫy môi trường và phối hợp bao vây người chơi thông minh hơn.
  • Hệ thống nhiệm vụ và Thành tựu (Achievements): Tích hợp dịch vụ Google Play Games Services để lưu trữ điểm số cao, mở khóa thành tựu và thi đấu trên bảng xếp hạng thế giới.
  • Mở rộng đa nền tảng: Biên dịch phiên bản dành cho hệ điều hành iOS và phát hành bản thử nghiệm WebGL trên nền tảng Itch.io.

Đối tượng hưởng lợi

  • Sinh viên chuyên ngành CNTT / Kỹ thuật Phần mềm: Tiếp cận mã nguồn mẫu chuẩn mực, nắm vững cách vận hành của các Design Pattern kinh điển trong thực tế và quy trình sản xuất phần mềm khép kín từ khâu tiếp nhận yêu cầu đến đóng gói thành phẩm.
  • Lập trình viên Game Indie: Sở hữu một bộ khung (Framework) 2D Top-down hoàn chỉnh, tiết kiệm ước tính 60-80 giờ lập trình cơ bản đối với hệ thống Joystick, Controller, Audio Manager và UI State Handler.
  • Nhà nghiên cứu / Giảng viên: Sử dụng làm đề tài mẫu trong giảng dạy học phần Phát triển Ứng dụng Di động và Đồ họa Máy tính, minh họa trực quan sự khác biệt giữa tối ưu hóa và không tối ưu hóa tài nguyên phần cứng.

Câu hỏi thường gặp

1. Cấu hình phần cứng tối thiểu trên điện thoại Android để chơi game là gì?

Game được tối ưu hóa sâu với công nghệ 2D Sprite, do đó chỉ yêu cầu thiết bị chạy Android 8.0 trở lên, tối thiểu 2GB RAM và chip xử lý tương đương Snapdragon 450 hoặc MediaTek Helio P22 là có thể đạt tốc độ 60 FPS mượt mà.

2. Tại sao dự án lại lựa chọn ScriptableObject thay vì lưu thông số vũ khí trong cơ sở dữ liệu SQLite hay JSON?

ScriptableObject được tích hợp nguyên bản vào bộ nhớ của Unity Engine, cho phép nạp dữ liệu tức thì (Zero-parse overhead), hỗ trợ trực quan hóa việc chỉnh sửa ngay trên Inspector và giảm đáng kể thời gian đọc/ghi (I/O) trong quá trình game đang chạy.

3. Làm thế nào để giải quyết triệt để hiện tượng rác bộ nhớ (Garbage Collection) khi hàng trăm viên đạn được bắn ra liên tục?

Dự án áp dụng triệt để mẫu thiết kế Object Pooling. Thay vì liên tục gọi hàm Instantiate()Destroy(), các viên đạn và quái vật được khởi tạo sẵn trong một danh sách chờ (Pool List) ngay từ khi bắt đầu màn chơi và chỉ chuyển đổi trạng thái SetActive(true/false), triệt tiêu hoàn toàn các đợt quét bộ nhớ của Garbage Collector.

4. Việc sử dụng Scripting Backend IL2CPP mang lại lợi ích gì so với Mono truyền thống?

IL2CPP chuyển đổi toàn bộ mã trung gian C# IL sang mã nguồn C++ nguyên bản trước khi biên dịch ra mã máy. Điều này giúp tăng hiệu năng thực thi của CPU lên 20-30%, bảo mật mã nguồn tốt hơn chống lại việc decompile ngược và đáp ứng bắt buộc tiêu chuẩn 64-bit của Google Play Store.

5. Dự án xử lý sự kiện giao diện và thay đổi chỉ số nhân vật như thế nào để đảm bảo tính module hóa?

Hệ thống sử dụng cơ chế C# Actions & Events (Observer Pattern). Khi máu của Ruby giảm, lớp PlayerHealth chỉ đơn thuần phát đi một sự kiện OnHealthChanged?.Invoke(currentHealth, maxHealth). Các lớp UIManager, SoundEffectManager tự đăng ký lắng nghe sự kiện này và tự cập nhật giao diện mà không cần biết logic tính toán trừ máu diễn ra ở đâu.


Kết luận

Đồ án tốt nghiệp "Xây dựng Game 2D trên Unity" do sinh viên Võ Nguyễn Minh Thư thực hiện đã hoàn thành xuất sắc toàn bộ các mục tiêu nghiên cứu và ứng dụng kỹ thuật đặt ra. Dự án không chỉ dừng lại ở việc tạo ra một trò chơi 2D sinh tồn hấp dẫn trên Android mà còn thể hiện năng lực chuyên môn vững vàng trong việc tổ chức kiến trúc phần mềm, áp dụng các mẫu thiết kế hướng đối tượng hiện đại và tối ưu hóa hiệu năng phần cứng di động. Đây là nguồn tư liệu học tập và tham khảo kỹ thuật giá trị, đóng góp thiết thực cho cộng đồng phát triển game và sinh viên ngành Công nghệ thông tin. Hãy tải về bản build, trải nghiệm gameplay và khám phá cấu trúc mã nguồn để áp dụng cho các dự án phát triển game tiếp theo của bạn!