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

24 Tháng sáu, 2024

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.

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

Giới thiệu đủ rồi, bây giờ chúng ta cùng bắt tay vào code trong Unity.
Ở đây, mình 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í.

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

Đầ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

Cuối cùng chúng ta chỉ cần viết hàm xử lý Input trong hàm Update của InputController là xong.

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.

Để 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;
        }
    }
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...
Hướng dẫn lấy đường dẫn các page Woocommerce 3.x
Chắc hẳn ai dùng Woocommerce đều sẽ muốn hiển thị đường dẫn của trang tài khoản, cửa hàng, thanh toán, giỏ hàng,.. Có rất nhiều phương án xử lý...
Hướng dẫn xóa san-pham , danh-muc-san-pham trong đường dẫn sản phẩm Woocommerce
Với mặc định của Woocommerce, chi tiết sản phẩm sẽ có dạng domain/san-pham/ten-san-pham và danh mục sản phẩm sẽ ở dạng domain/danh-muc-san-pham/ten-danh-muc. Một phần đường dẫn như vậy sẽ...