Command Pattern và ứng dụng trong Unity – Phần 1

24 Tháng 6, 2024
(1 đánh giá)

Trong lập trình game, việc tương tác, điều khiển của người chơi với game là rất quan trọng. Do vậy, command pattern được sử dụng rộng rãi và phổ biến. Trong bài viết này, chúng ta sẽ tìm hiểu cách triển khai Command Pattern trong Unity để tối ưu hóa hệ thống điều khiển game

Command pattern là gì?

“In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.”

Theo wikipedia

Lý thuyết là vậy. Song, command pattern có thể ứng dụng được vào những gì trong lập trình game mới là điều mình muốn đề cập đến. Trong phạm vi bài viết này, mình sẽ giải thích và hướng dẫn một số ứng dụng dưới đây:

  • Xây dựng hệ thống điều khiển, tương tác với nhân vật trong game.
  • Cho phép người chơi sửa đổi các nút bấm mặc định theo ý mình.
  • Lưu và diễn lại các hành động của nhân vật.
Command trong CS
Command trong CS

Xây dựng hệ thống điều khiển trong game

Một lỗi mà những ai mới bắt đầu học lập trình game (kể cả mình) thường mắc phải đó là code “cứng” phần điều khiển nhân vật vào class của nhân vật.

Về cơ bản thì code thế này khá ổn cho đến khi có những phát sinh như bạn muốn thay đổi phim điều khiển mà không phải code lại, chơi coop với bạn bè trên cùng một máy,…

Đây là một ví dụ để các bạn dễ hình dung hơn về command pattern:

Không dùng command
Không dùng command
Dùng command
Dùng command

Cách triển khai Command Pattern trong Unity

Xây dựng lớp nhân vật (Unit)

Ở đây, chúng ta sẽ tạo một class Unit với những hành động cơ bản là nhảy, bắn và thay đổi vũ khí. Lớp này cung cấp các phương thức cho nhân vật, nhưng không chứa logic điều khiển trực tiếp.

public class Unit : MonoBehaviour
{
    public virtual void Jump()
    {
    }
    public virtual void Fire()
    {
    }
    public virtual void SwapWeapon()
    {
    }
}

Tạo lớp Command

Đầu tiên là tạo một class abstract BaseCommand để cấu trúc cơ bản cho một command:

public abstract class BaseCommand
{
    public abstract void Execute(Unit unit);
}

Sau đó, command cho các hành động khác đều kế thừa từ lớp BaseCommand:

public class FireCommand : BaseCommand
{
    public override void Execute(Unit unit)
    {
        unit.Fire();
    }
}
public class JumpCommand : BaseCommand
{
    public override void Execute(Unit unit)
    {
        unit.Jump();
    }
}
public class SwapCommand : BaseCommand
{
    public override void Execute(Unit unit)
    {
        unit.SwapWeapon();
    }
}

Vậy là chúng ta đã dựng xong các lệnh command cơ bản. Như mình đã nói ở trên là không nên code “cứng” phần Input vào trong class Unit. Do đó, chúng ta sẽ tạo một GameObject riêng biệt là InputController và class InputController.

Tạo GameObject riêng biệt
Tạo GameObject riêng biệt

Quản lý Input bằng Command Pattern

Thay vì viết logic điều khiển trực tiếp trong nhân vật, chúng ta sử dụng một GameObject riêng để quản lý input, Lớp này giúp tách biệt xử lý input khỏi nhân vật, giúp dễ dàng tùy chỉnh điều khiển, hỗ trợ nhiều kiểu input:

public class InputController : MonoBehaviour
{
    public Unit unitControl;
    public KeyCode keyJump;
    public KeyCode keyFire;
    public KeyCode keySwapWeapon;
    private JumpCommand jumpCmd = new JumpCommand();
    private FireCommand fireCmd = new FireCommand();
    private SwapCommand swapCmd = new SwapCommand();
    private void Update()
    {
        ProcessInput();
    }
    private void ProcessInput()
    {
        if (Input.GetKeyDown(keyJump))
        {
            jumpCmd.Execute(unitControl);
        }
        else if (Input.GetKeyDown(keyFire))
        {
            fireCmd.Execute(unitControl);
        }
        else if (Input.GetKeyDown(keySwapWeapon))
        {
            swapCmd.Execute(unitControl);
        }
    }
  }

Vậy phải làm sao để thay đổi phím điều khiển hay đổi sang điều khiển nhân vật khác. Những hàm xử lý đó chúng ta chỉ cần viết thêm vào InputController là được.

Tùy chỉnh phím điều khiển

Để thay đổi phím, chúng ta cần thêm enum để phân biệt các loại phím tương ứng với các hành động của unit:

// Thay đổi unit điều khiển
  public void ChangeUnitControl(Unit newUnit)
    {
        unitControl = newUnit;
    }
// Thay đổi phím điều khiển
    public void ChangeKeyCode(KeyAction keyAction, KeyCode newKeyCode)
    {
        switch (keyAction)
        {
            case KeyAction.Jump:
                keyJump = newKeyCode;
                break;
            case KeyAction.Fire:
                keyFire = newKeyCode;
                break;
            case KeyAction.SwapWeapon:
                keySwapWeapon = newKeyCode;
                break;
        }
    }

Với cách này, người chơi có thể tự do thiết lập phím điều khiển mà không cần thay đổi mã nguồn.

Command Pattern không chỉ giúp hệ thống điều khiển trong game trở nên linh hoạt, mà còn giúp code dễ bảo trì và mở rộng. Nếu bạn đang xây dựng một game với nhiều hành động, đây là một giải pháp tối ưu đáng để áp dụng.

Hy vọng hướng dẫn này Gini Webseo đã giúp bạn hiểu rõ hơn về Command Pattern trong Unity. Nếu bạn có thắc mắc hoặc muốn tìm hiểu thêm về các mẫu thiết kế khác, hãy để lại bình luận và cùng nhau trao đổi nhé!

guest
0 Góp ý
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Phản hồi nội tuyến
Xem tất cả bình luận
Tin tức liên quan
Hướng dẫn tạo sản phẩm Woocommerce có biến thể đẹp mắt
Mình đọc bình luận thấy khá nhiều bạn kêu gặp khó khăn trong vấn đề tạo sản phẩm có biến thể, hay sản phẩm có biến thể không được...
Hiển thị mô tả ngắn trong WordPress
Khi hiển thị bài viết ở trang lưu trữ hay trang chủ, ngoài tiêu đề và ảnh đại diện, thứ mà không thể thiếu chính là mô tả ngắn...
Hướng dẫn phân trang trong WordPress
Khi ở trang lưu trữ, chắc hẳn các bạn gặp không ít khó khăn trong việc phân trang hoặc cố gắng loay hoay nhưng không được. Bài viết này...