Hero image

Mẹo về đặt tên và kiểu mã cho lập trình C# trong Unity

Trang web này đã được dịch bằng máy để thuận tiện cho bạn. Chúng tôi không thể đảm bảo tính chính xác hoặc độ tin cậy của nội dung được dịch. Nếu bạn có thắc mắc về tính chính xác của nội dung được dịch, vui lòng tham khảo phiên bản tiếng Anh chính thức của trang web.

Mặc dù có thể không có một cách đúng duy nhất để định dạng mã C#, việc thống nhất một phong cách nhất quán trong toàn bộ nhóm có thể tạo ra một codebase sạch hơn, dễ đọc hơn và có khả năng mở rộng tốt hơn. Một cẩm nang hướng dẫn phong cách được tổ chức tốt có thể giúp bạn kiểm soát những điểm không nhất quán để tạo ra một sản phẩm cuối cùng mạch lạc.

Tên của các biến, lớp và phương thức của bạn không chỉ đơn thuần là những nhãn mác. Chúng mang trọng lượng và ý nghĩa. Cách đặt tên tốt ảnh hưởng đến việc người đọc chương trình của bạn có thể hiểu được ý tưởng mà bạn đang cố gắng truyền tải như thế nào.

Trang này cung cấp các mẹo và những điểm cần lưu ý quan trọng về quy ước đặt tên và định dạng mã khi tạo hướng dẫn phong cách riêng của bạn.

Ghi chú : Các khuyến nghị được chia sẻ ở đây dựa trên những khuyến nghị do Microsoft cung cấp. Các quy tắc hướng dẫn về phong cách viết mã tốt nhất là những quy tắc phù hợp nhất với nhu cầu của nhóm bạn.

Bạn có thể tìm thấy ví dụ về hướng dẫn kiểu mã ở đây hoặc tải xuống toàn bộ sách điện tử, Sử dụng hướng dẫn kiểu mã C# để có mã trò chơi sạch và có khả năng mở rộng (phiên bản Unity 6) .

Tên định danh

Định danh là bất kỳ tên nào bạn gán cho một kiểu dữ liệu (lớp, giao diện, cấu trúc, ủy quyền hoặc kiểu liệt kê), thành viên, biến hoặc không gian tên.

Hãy tránh sử dụng các ký tự đặc biệt (dấu gạch chéo ngược, ký hiệu, ký tự Unicode) trong tên định danh của bạn, mặc dù C# cho phép chúng. Những điều này có thể gây xung đột với một số công cụ dòng lệnh Unity . Tránh sử dụng các ký tự lạ để đảm bảo khả năng tương thích với hầu hết các nền tảng.

Thuật ngữ vỏ bọc

Bạn không thể định nghĩa biến có chứa dấu cách trong tên vì C# sử dụng ký tự dấu cách để phân tách các định danh. Việc sử dụng các quy tắc viết hoa/viết thường có thể giúp giảm bớt vấn đề phải sử dụng các tên hoặc cụm từ ghép trong mã nguồn.

Dưới đây là một số quy ước đặt tên và viết hoa phổ biến:

Camel case (camelCase)

Hay còn gọi là kiểu viết hoa chữ cái đầu mỗi từ (camel caps), kiểu viết này là cách viết các cụm từ không có khoảng trắng hoặc dấu chấm câu, chỉ dùng một chữ cái viết hoa để phân tách các từ. Chữ cái đầu tiên là chữ thường. Các biến cục bộ và tham số phương thức được viết theo kiểu camel case. Ví dụ:


examplePlayerController

maxHealthPoints

endOfFile

Pascal case (PascalCase)

Pascal case là một biến thể của camel case, trong đó chữ cái đầu tiên được viết hoa. Hãy sử dụng điều này cho tên lớp, trường công khai và phương thức trong quá trình phát triển Unity . Ví dụ:


ExamplePlayerController

MaxHealthPoints

EndOfFile

Snake case (snake_case)

Trong trường hợp này, khoảng trắng giữa các từ được thay thế bằng ký tự gạch dưới. Ví dụ:

example_player_controller

max_health_points

end_of_file

Hộp đựng kebab (kebab-case)

Ở đây, khoảng trắng giữa các từ được thay thế bằng dấu gạch ngang. Các từ xuất hiện trên một "xiên" gồm các ký tự gạch ngang. Ví dụ:

example-player-controller

Điểm sức khỏe tối đa

kết thúc tệp

quy ước đặt tên-phương pháp

Kiểu viết Kebab-case được sử dụng rộng rãi trong công nghệ web, đặc biệt là trong CSS. Chúng tôi cũng khuyến nghị sử dụng nó với UI Toolkit USS.

Ký hiệu Hungary

Tên biến hoặc hàm thường cho biết mục đích hoặc kiểu của nó. Ví dụ:

int iCounter

chuỗi strPlayerName


Ký hiệu tiếng Hungary là một quy ước cũ và không phổ biến trong quá trình phát triển Unity .

Các trường và biến

Hãy xem xét các quy tắc này đối với các biến và trường của bạn:

  • Hãy sử dụng danh từ làm tên biến: Tên biến cần phải mang tính mô tả, rõ ràng và không gây nhầm lẫn vì chúng đại diện cho một đối tượng hoặc trạng thái. Vì vậy, hãy sử dụng danh từ khi đặt tên cho chúng, trừ khi biến đó thuộc kiểu boolean (xem bên dưới).
  • Thêm tiền tố cho động từ vào các giá trị Boolean: Các biến này biểu thị giá trị đúng hoặc sai . Thông thường, chúng là câu trả lời cho một câu hỏi, chẳng hạn như - cầu thủ có đang chạy không? Trò chơi đã kết thúc chưa? Thêm động từ vào trước chúng để làm cho ý nghĩa của chúng rõ ràng hơn. Thông thường, thuộc tính này được đi kèm với mô tả hoặc điều kiện, ví dụ như isDead , isWalking , hasDamageMultiplier , v.v.
  • Hãy sử dụng những cái tên có ý nghĩa. Không nên viết tắt (trừ khi đó là toán học): Tên biến của bạn nên thể hiện rõ mục đích của chúng. Hãy chọn những cái tên dễ phát âm và dễ tìm kiếm – không chỉ cho đồng nghiệp của bạn mà còn để cung cấp thêm ngữ cảnh cho mã khi sử dụng các công cụ AI, vì điều này có thể góp phần tạo ra mã và đề xuất chính xác hơn. Hãy chọn những tên định danh dễ đọc. Ví dụ, một thuộc tính có tên HorizontalAlignment dễ đọc hơn so với AlignmentHorizontal. Biến chỉ gồm một chữ cái thì được chấp nhận trong vòng lặp và các biểu thức toán học, nhưng ngoài ra thì không nên viết tắt. Sự rõ ràng quan trọng hơn bất kỳ thời gian nào tiết kiệm được nhờ việc lược bỏ một vài nguyên âm. Bạn có thể muốn sử dụng những cái tên ngắn gọn, "vô nghĩa" khi tạo nguyên mẫu, nhưng điều này sẽ không giúp bạn tiết kiệm thời gian nếu cần phải chỉnh sửa lại mã sau này. Hãy chọn những cái tên có ý nghĩa ngay từ đầu.
  • Sử dụng kiểu Pascal Case (MyPropertyName) cho các trường công khai. Sử dụng kiểu viết hoa đầu câu (camel case) cho các biến riêng tư: Để thay thế cho các trường công khai, hãy sử dụng Thuộc tính với phương thức getter công khai (xem phần Định dạng ở trên và dưới).
  • Hãy cân nhắc sử dụng tiền tố hoặc mã hóa đặc biệt: Một số hướng dẫn đề xuất thêm tiền tố dấu gạch dưới (_) vào các biến thành viên riêng tư để phân biệt chúng với các biến cục bộ. Trong hướng dẫn về kiểu viết mã, chúng tôi sử dụng tiền tố cho các biến thành viên riêng tư (m_), hằng số (k_) hoặc biến tĩnh (s_), để tên biến có thể tiết lộ nhiều thông tin hơn về biến đó chỉ trong nháy mắt. Ví dụ, movementSpeed ​​trở thành m_movementSpeed. Việc kết hợp PascalCase với tiền tố như m_MovementSpeed ​​cũng là một lựa chọn nhưng thường ít được sử dụng trong C# hiện đại. Ngoài ra, bạn cũng có thể sử dụng từ khóa `this` để phân biệt giữa biến thành viên và biến cục bộ trong ngữ cảnh và bỏ qua tiền tố. Các trường và thuộc tính công khai thường không có tiền tố. Các biến cục bộ và tham số sử dụng kiểu chữ viết hoa xen kẽ (camel case) mà không có tiền tố. Nhiều nhà phát triển bỏ qua những công cụ này và thay vào đó dựa vào trình soạn thảo. Tuy nhiên, không phải tất cả các IDE đều hỗ trợ tô sáng và mã màu, và một số công cụ thậm chí không thể hiển thị ngữ cảnh phong phú.
  • Các trường được tự động khởi tạo với giá trị mặc định: Giá trị mặc định thường là 0 đối với các kiểu dữ liệu số như int, trong khi các trường kiểu tham chiếu (ví dụ: đối tượng) được khởi tạo mặc định là null , và các trường boolean được khởi tạo mặc định là false. Do đó, việc thiết lập rõ ràng một trường về giá trị mặc định của nó thường là không cần thiết.
  • Đặt tên cho các biến hằng số với tiền tố k_ và theo định dạng PascalCase: Điều này giúp phân biệt hằng số với các biến hoặc thuộc tính thông thường, đồng thời giúp mã dễ đọc và dễ bảo trì hơn.
  • Hãy chỉ định (hoặc bỏ qua) các yếu tố điều chỉnh cấp độ truy cập một cách nhất quán: Nếu bạn bỏ qua từ khóa chỉ định quyền truy cập, trình biên dịch sẽ mặc định quyền truy cập là private. Cách này hoạt động tốt, nhưng hãy nhất quán trong cách bạn bỏ qua bộ điều chỉnh quyền truy cập mặc định. Theo hướng dẫn của MSFT, nên chỉ rõ "riêng tư" để làm rõ cấp độ truy cập và tránh mọi sự mơ hồ. Các hướng dẫn khác cho rằng bạn nên loại bỏ các từ khóa truy cập dư thừa (bỏ từ khóa 'private' ở phạm vi kiểu) và tương tự, loại bỏ các giá trị khởi tạo dư thừa (ví dụ: không dùng '= 0' cho kiểu int, '= null' cho kiểu tham chiếu, v.v.). Hãy nhớ rằng bạn cần sử dụng từ khóa `protected` nếu muốn sử dụng nó trong một lớp con sau này. Tuy nhiên, nhìn chung, việc chỉ định các yếu tố điều chỉnh cấp độ truy cập được coi là một thực hành tốt.
  • Ưu tiên tính dễ đọc hơn tính ngắn gọn: Như ví dụ này từ tài liệu của MSFT cho thấy, tên thuộc tính CanScrollHorizontally tốt hơn ScrollableX (một tham chiếu khó hiểu đến trục X).
  • Mỗi dòng chỉ khai báo một biến: Nó kém nhỏ gọn hơn, nhưng lại giúp dễ đọc hơn.
  • Tránh đặt tên trùng lặp: Nếu lớp của bạn có tên là Player, bạn không cần tạo các biến thành viên có tên là PlayerScore hoặc PlayerTarget. Cắt bớt chúng để hiển thị Điểm số hoặc Mục tiêu.
  • Loại bỏ các giá trị khởi tạo dư thừa (ví dụ: không có '= 0' trên các số nguyên, '= null' trên các kiểu tham chiếu, v.v.).
  • Tránh dùng những câu nói đùa hoặc chơi chữ: Mặc dù những cái tên như infiniteMonkeys hay dudeWheresMyChar có thể gây cười lúc này, nhưng chúng sẽ không còn phù hợp sau vài chục lần đọc, và quan trọng hơn, chúng vi phạm mục tiêu đã nêu trước đó của chúng ta là đặt tên sao cho thể hiện được ngữ cảnh.
  • Chỉ nên sử dụng từ khóa var cho các biến cục bộ được khai báo ngầm định nếu điều đó giúp cải thiện khả năng đọc hiểu và kiểu dữ liệu rõ ràng: Hãy chỉ rõ khi nào nên sử dụng từ khóa `var` trong hướng dẫn kiểu viết mã của bạn. Ví dụ, nhiều nhà phát triển tránh sử dụng từ khóa `var` khi nó che giấu kiểu dữ liệu của biến hoặc với các kiểu dữ liệu nguyên thủy bên ngoài vòng lặp.
Bảng trường và biến
// VÍ DỤ: Các biến số công cộng và tư nhân

public float DamageMultiplier = 1.5f;
Cổ phiếu MaxHealth float công khai;
public boolean IsInvincible;

private boolean _isDead;
private float _currentHealth;

// tham số
public void InflictDamage(float damage, boolean isSpecialDamage)
{
    // biến cục bộ
    int totalDamage = damage;

    // Biến cục bộ so với biến thành viên công khai
    nếu (làSátThiệtĐặcBiệt)
    {
    	Tổng sát thương *= Hệ số sát thương;
    }

    // Biến cục bộ so với biến thành viên riêng tư
    if (totalDamage > _currentHealth)
    {
        /// ...
    }
}

Liệt kê

Enum là các kiểu giá trị đặc biệt được định nghĩa bởi một tập hợp các hằng số có tên. Theo mặc định, các hằng số là số nguyên, bắt đầu từ số không.

Hãy sử dụng kiểu chữ Pascal cho tên và giá trị của kiểu liệt kê (enum). Bạn có thể đặt các kiểu liệt kê công khai bên ngoài một lớp để biến chúng thành kiểu toàn cục. Hãy sử dụng danh từ số ít cho tên kiểu liệt kê vì nó đại diện cho một giá trị duy nhất từ ​​một tập hợp các giá trị có thể có. Chúng không nên có tiền tố hoặc hậu tố.

Ghi chú : Các kiểu liệt kê bitwise được đánh dấu bằng thuộc tính System.FlagsAttribute là ngoại lệ đối với quy tắc này. Bạn thường dùng dạng số nhiều cho những từ này vì chúng đại diện cho nhiều loại khác nhau.


// VÍ DỤ: Enum sử dụng danh từ số ít…
kiểu liệt kê công khai WeaponType
{
    Knife,
    Gun,
    RocketLauncher, 
    BFG
}

kiểu liệt kê công khai FireMode
{
    Không có = 0,
    Single = 5,
    Burst = 7,
    Auto = 8, 
}

// VÍ DỤ: … nhưng một kiểu liệt kê bitwise lại ở dạng số nhiều.

[Cờ] 
kiểu liệt kê công khai Chế độ tấn công 
{
  // Hệ thập phân // Hệ nhị phân
   None = 0,                          // 000000
   Melee = 1,                         // 000001
   Khoảng cách = 2, // 000010
   Special = 4,                       // 000100

   MeleeAndSpecial = Melee | Special  // 000101
}

Các lớp và giao diện

Hãy tuân theo các quy tắc chuẩn này khi đặt tên cho các lớp và giao diện của bạn:

  • Hãy sử dụng danh từ hoặc cụm danh từ theo kiểu Pascal cho tên lớp: Điều này giúp phân biệt tên kiểu với tên phương thức, vốn được đặt tên bằng các cụm động từ.
  • Nếu bạn có Monobehaviour trong một tệp, tên tệp nguồn phải khớp với: Bạn có thể có các lớp nội bộ khác trong cùng một tệp, nhưng chỉ nên có một Monobehaviour duy nhất trong mỗi tệp.
  • Thêm chữ I viết hoa vào đầu tên giao diện: Tiếp theo đó là một tính từ mô tả chức năng của nó.
// VÍ DỤ: Định dạng lớp
public class ExampleClass : MonoBehaviour
{

    public int PublicField;
    public static int MyStaticField;

    private int _packagePrivate;
    private int _myPrivate;

    private static int _myPrivate;

    protected int _myProtected;

    public void DoSomething()
    {

    }
}

// VÍ DỤ: Giao diện
giao diện công cộng IKillable
{
    void Kill();
}

giao diện công cộng IDamageable
{
    void Damage(T damageTaken);
}

Phương pháp

Trong C#, mọi lệnh được thực thi đều diễn ra trong ngữ cảnh của một phương thức.

Lưu ý : "Hàm" và "phương thức" thường được sử dụng thay thế cho nhau trong quá trình phát triển Unity . Tuy nhiên, vì trong C# bạn không thể viết một hàm mà không tích hợp nó vào một lớp, nên "phương thức" là thuật ngữ được chấp nhận.

Các phương thức thực hiện các hành động, vì vậy hãy áp dụng các quy tắc này để đặt tên cho chúng một cách phù hợp:

  • Hãy bắt đầu tên bằng một động từ hoặc cụm động từ: Thêm ngữ cảnh nếu cần thiết. Ví dụ: GetDirection , FindTarget , v.v.
  • Sử dụng kiểu viết hoa đầu mỗi từ (camel case) cho các tham số: Định dạng các tham số được truyền vào phương thức, ví dụ như các biến cục bộ.
  • Các phương thức trả về boolean nên đặt câu hỏi: Tương tự như các biến Boolean, hãy thêm tiền tố là một động từ vào các phương thức nếu chúng trả về điều kiện đúng/sai. Điều này thể hiện chúng dưới dạng câu hỏi, ví dụ: IsGameOver , HasStartedTurn .
// VÍ DỤ: Phương pháp bắt đầu bằng một động từ.
public void SetInitialPosition(float x, float y, float z)
{
    transform.position = new Vector3(x, y, z);
}

// VÍ DỤ: Các phương thức đặt ra câu hỏi khi chúng trả về boolean.
public boolean IsNewPosition(Vector3 currentPosition)
{
    return (transform.position == newPosition);
}

Sự kiện và người tổ chức sự kiện

Các sự kiện trong C# triển khai mẫu thiết kế Observer . Mẫu thiết kế phần mềm này định nghĩa một mối quan hệ trong đó một đối tượng, được gọi là chủ thể (hoặc nhà xuất bản), có thể thông báo cho một danh sách các đối tượng phụ thuộc được gọi là người quan sát.(hoặc người đăng ký). Như vậy, chủ thể có thể truyền tải những thay đổi trạng thái đến những người quan sát mà không cần liên kết chặt chẽ các đối tượng liên quan. Bạn có thể tìm hiểu thêm về cách sử dụng observer và các mẫu thiết kế khác trong dự án Unity của mình trong sách điện tử "Nâng cao chất lượng mã nguồn với các mẫu thiết kế và SOLID" .

Sử dụng động từ

Hãy đặt tên cho sự kiện bằng một cụm động từ. Hãy chọn một cái tên thể hiện chính xác sự thay đổi trạng thái. Sử dụng thì hiện tại hoặc quá khứ phân từ để chỉ các sự kiện “trước” hoặc “sau”. Ví dụ, bạn có thể chỉ định “OpeningDoor” cho sự kiện trước khi mở cửa hoặc “DoorOpened” cho sự kiện sau đó.

Sử dụng System.Action

Trong hầu hết các trường hợp, ủy quyền Action có thể xử lý các sự kiện cần thiết cho trò chơi. Bạn có thể truyền từ 0 đến 16 tham số đầu vào thuộc các kiểu dữ liệu khác nhau với kiểu trả về là void. Việc sử dụng delegate được định sẵn giúp tiết kiệm mã.

Ghi chú : Bạn cũng có thể sử dụng các delegate EventHandler hoặc EventHandler . Thống nhất với cả nhóm về cách thức mỗi người sẽ thực hiện các sự kiện.

// VÍ DỤ: Sự kiện 

// sử dụng ủy quyền System.Action

sự kiện công khai Hành động Mở cửa; // sự kiện trước đó
sự kiện công khai Hành động Cửa Mở; // sự kiện sau

Hành động sự kiện công cộng Điểm số;
Hành động sự kiện công cộng Chuyện đã xảy ra;

Thêm tiền tố “On” vào phương pháp.

Đối tượng kích hoạt sự kiện thường thực hiện điều đó từ một phương thức có tiền tố là “On,” ví dụ: “OnOpeningDoor” hoặc “OnDoorOpened”.

// Kích hoạt sự kiện nếu bạn có người đăng ký
public void OnDoorOpened()
{
    DoorOpened?.Invoke();
}

public void OnPointsScored(int points)
{
    PointsScored?.Invoke(points);
}

Thêm tên môn học và dấu gạch dưới vào đầu câu.

Nếu đối tượng được đặt tên là “GameEvents”, các trình quan sát của bạn có thể có một phương thức được gọi là “GameEvents_OpeningDoor” hoặc “GameEvents_DoorOpened”. Lưu ý rằng đây được gọi là "phương thức xử lý sự kiện", không nên nhầm lẫn với ủy quyền EventHandler.

Hãy sử dụng EventArgs một cách cẩn thận.

Chỉ tạo các EventArgs tùy chỉnh khi cần thiết. Nếu bạn cần truyền dữ liệu tùy chỉnh cho Sự kiện của mình, tạo một kiểu EventArgs mới, kế thừa từ System.EventArgs.hoặc từ một cấu trúc tùy chỉnh.

// Định nghĩa EventArgs nếu cần

// VÍ DỤ: Cấu trúc tùy chỉnh chỉ đọc, được sử dụng để truyền ID và Màu sắc.
cấu trúc công khai CustomEventArgs
{
    public int ObjectID { get; }
    public Color Color { get; }

    public CustomEventArgs(int objectId, Color color)
    {
        this.ObjectID = objectId;
        this.Color = color;
    }
}

Không gian tên

Hãy sử dụng không gian tên để đảm bảo rằng các lớp, giao diện, kiểu liệt kê, v.v. của bạn sẽ không xung đột với các lớp, giao diện, kiểu liệt kê hiện có từ các không gian tên khác hoặc không gian tên toàn cục. Không gian tên cũng có thể ngăn ngừa xung đột với các tài sản của bên thứ ba từ Asset Store.

Khi áp dụng không gian tên:

  • Hãy sử dụng PascalCase mà không có các ký hiệu đặc biệt hoặc dấu gạch dưới.
  • Thêm lệnh `using` ở đầu tệp để tránh phải gõ lại tiền tố không gian tên nhiều lần.
  • Hãy tạo cả các không gian tên con nữa. Sử dụng toán tử dấu chấm (.) để phân tách các cấp độ tên, cho phép bạn sắp xếp các tập lệnh của mình thành các danh mục phân cấp. Ví dụ, bạn có thể tạo MyApplication.GameFlow, MyApplication.AI, MyApplication.UI, v.v. để chứa các thành phần logic khác nhau của trò chơi.
  • Nhìn chung, việc sử dụng các không gian tên phản ánh cấu trúc thư mục của dự án được coi là một thực tiễn tốt, vì việc nhóm các lớp và thành phần có liên quan lại với nhau một cách hợp lý cũng giúp dễ dàng tìm kiếm và hiểu cấu trúc của mã nguồn.
không gian tên Enemy 
{
    public class Controller1 : MonoBehaviour 
    {
        ...
    }
    
    public class Controller2 : MonoBehaviour 
    {
        ...
    }
}

Tiền tố

Trong mã lập trình, các lớp này được gọi tương ứng là Enemy.Controller1 và Enemy.Controller2 . Thêm dòng `using` để tiết kiệm thời gian gõ tiền tố:

Sử dụng Enemy;

Khi trình biên dịch tìm thấy tên lớp Controller1 và Controller2 , nó hiểu rằng bạn đang muốn nói đến Enemy.Controller1 và Enemy.Controller2 .

Nếu đoạn mã cần tham chiếu đến các lớp có cùng tên từ các không gian tên khác nhau, hãy sử dụng tiền tố để phân biệt chúng. Ví dụ, nếu bạn có lớp Controller1 và Controller2 trong không gian tên Player , bạn có thể viết là Player.Controller1 và Player.Controller2 để tránh xung đột. Nếu không, trình biên dịch sẽ báo lỗi.

Sử dụng Enemy;

Tìm hiểu thêm các mẹo về phong cách viết mã

Tìm hiểu thêm về định dạng chung tại đây hoặc xem toàn bộ sách điện tử . Bạn cũng có thể tham khảo ví dụ về hướng dẫn phong cách viết mã của chúng tôi.