
Советы по наименованию и стилю кода для сценариев C# в Unity
Эта веб-страница была переведена с помощью машинного перевода для вашего удобства. Мы не можем гарантировать точность или надежность переведенного контента. Если у вас есть вопросы о точности переведенного контента, обращайтесь к официальной английской версии веб-страницы.
Хотя может не быть единственно правильного способа форматирования вашего кода C#, согласование единого стиля в вашей команде может привести к более чистой, читаемой и масштабируемой кодовой базе. Хорошо организованное руководство по стилю может помочь вам устранить несоответствия и создать единый конечный продукт. Эта страница предоставляет советы и ключевые моменты, которые следует учитывать при создании собственных руководств по наименованию и форматированию кода.
Примечание: Рекомендации, представленные здесь, основаны на тех, что предоставлены Microsoft. Лучшие правила руководства по стилю кода - это те, которые лучше всего подходят для потребностей вашей команды.
Вы можете найти пример руководства по стилю кода здесь или скачать полную электронную книгу, Создание руководства по стилю C# : Пишите более чистый код, который масштабируется.
Терминология написания
Вы не можете определять переменные с пробелами в имени, потому что C# использует пробел для разделения идентификаторов. Схемы написания могут облегчить проблему использования составных имен или фраз в исходном коде.
Ниже перечислены несколько известных соглашений по именованию и написанию:
Верблюжий регистр
Также известный как верблюжий регистр, верблюжий регистр — это практика написания фраз без пробелов или знаков препинания, разделяя слова одной заглавной буквой. Первая буква пишется в нижнем регистре.
Как правило, локальные переменные и параметры методов пишутся в верблюжьем регистре. Например:
examplePlayerController
maxHealthPoints
endOfFile
Паскаль регистр
Паскаль регистр — это вариация верблюжьего регистра, где первая буква пишется с заглавной буквы. Используйте это для имен классов и методов в разработке Unity. Публичные поля также могут быть в паскаль регистре. Например:
ExamplePlayerController
MaxHealthPoints
КонецФайла
Змеиный регистр
В этом случае пробелы между словами заменяются символом подчеркивания. Например:
example_player_controller
max_health_points
end_of_file
Кебабный стиль
Здесь пробелы между словами заменяются дефисами. Слова затем появляются на своеобразном «шпажке» из дефисов. Например:
example-player-controller
Max-health-points
конец-файла
Проблема с кебабным стилем в том, что многие языки программирования используют дефис как знак минус. Кроме того, некоторые языки интерпретируют числа, разделенные дефисами, как календарные даты.
Венгерская нотация
Имя переменной или функции часто указывает на ее намерение или тип. Например:
int iCounter
string strPlayerName
Венгерская нотация — это старая традиция и не часто используется в разработке Unity.

Поля и переменные
Рассмотрите эти правила для ваших переменных и полей:
- Используйте существительные для имен переменных: Имена переменных должны быть ясными и описательными, так как они представляют собой конкретную вещь или состояние. Используйте существительное при их именовании, за исключением случаев, когда переменная типа bool (см. ниже).
- Добавьте к булевым переменным префикс с глаголом: Эти переменные указывают на истинное или ложное значение. Часто они являются ответом на вопрос, такой как: Игрок бежит? Игра окончена?
- Представьте их с помощью глагола, чтобы сделать их значение более очевидным. Часто это сочетается с описанием или условием, например, isDead, isWalking, hasDamageMultiplier и т.д.
- Используйте значимые имена. Не сокращайте (если это не математика): Имена ваших переменных будут раскрывать их намерение. Выбирайте имена, которые легко произносить и искать.
- Хотя переменные с одной буквой подходят для циклов и математических выражений, не сокращайте в других ситуациях. Ясность важнее, чем любое время, сэкономленное на опущении нескольких гласных.
- Для быстрого прототипирования вы можете временно использовать короткие "мусорные" имена, а затем переработать их на более значимые имена позже.
- Используйте PascalCase для публичных полей и camelCase для приватных переменных: В качестве альтернативы публичным полям используйте свойства с публичным "геттером" (см. предыдущие и последующие разделы).
- Избегайте слишком многих префиксов или специального кодирования: Вы можете добавлять префикс к приватным переменным-членам с помощью подчеркивания (_), чтобы отличать их от локальных переменных.
- В качестве альтернативы используйте ключевое слово this, чтобы различать переменные-члены и локальные переменные в контексте и пропустить префикс. Публичные поля и свойства, как правило, не имеют префиксов.
- Некоторые руководства по стилю используют префиксы для приватных переменных-членов (m_), констант (k_) или статических переменных (s_), чтобы имя могло раскрывать больше о переменной с первого взгляда.
- Многие разработчики избегают этого и полагаются на редактор вместо этого. Однако не все IDE поддерживают подсветку и цветовую кодировку, и некоторые инструменты вообще не могут показать богатый контекст. Учтите это, принимая решение о том, как (или если) вы будете применять префиксы вместе как команда.
- Последовательно указывайте (или опускайте) модификаторы уровня доступа: Если вы опустите модификатор доступа, компилятор предположит, что уровень доступа должен быть приватным. Это работает хорошо, но будьте последовательны в том, как вы опускаете модификатор доступа по умолчанию.
- Помните, что вам нужно будет использовать protected, если вы хотите это в подклассе позже.
// EXAMPLE: Public and private variables
public float DamageMultiplier = 1.5f;
public float MaxHealth;
public bool IsInvincible;
private bool _isDead;
private float _currentHealth;
// parameters
public void InflictDamage(float damage, bool isSpecialDamage)
{
// local variable
int totalDamage = damage;
// local variable versus public member variable
if (isSpecialDamage)
{
totalDamage *= DamageMultiplier;
}
// local variable versus private member variable
if (totalDamage > _currentHealth)
{
/// ...
}
}
Перечисления
Enums — это специальные типы значений, определенные набором именованных констант. По умолчанию константы являются целыми числами, начиная с нуля.
Используйте PascalCase для имен и значений перечислений. Вы можете разместить публичные перечисления вне класса, чтобы сделать их глобальными. Используйте существительное в единственном числе для имени перечисления.
Примечание: Перечисления с битовыми значениями, помеченные атрибутом System.FlagsAttribute, являются исключением из этого правила. Вы обычно делаете их во множественном числе, так как они представляют более одного типа.
// EXAMPLE: Enums use singular nouns …
public enum WeaponType
{
Knife,
Gun,
RocketLauncher,
BFG
}
public enum FireMode
{
None = 0,
Single = 5,
Burst = 7,
Auto = 8,
}
// EXAMPLE: … but a bitwise enum is plural.
[Flags]
public enum AttackModes
{
// Decimal // Binary
None = 0, // 000000
Melee = 1, // 000001
Ranged = 2, // 000010
Special = 4, // 000100
MeleeAndSpecial = Melee | Special // 000101
}
Классы и интерфейсы
Следуйте этим стандартным правилам при именовании ваших классов и интерфейсов:
Используйте существительные в PascalCase для имен классов: Это поможет вам организовать ваши классы.
Если у вас есть MonoBehaviour в файле, имя исходного файла должно совпадать: В файле могут быть другие внутренние классы, но только один MonoBehaviour должен существовать на файл.
Префиксируйте имена интерфейсов заглавной буквой “I”: Следуйте этому с прилагательным, которое описывает функциональность.
// EXAMPLE: Class formatting
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()
{
}
}
// EXAMPLE: Interfaces
public interface IKillable
{
void Kill();
}
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
Методы
В C# каждая выполняемая инструкция выполняется в контексте метода.
Методы выполняют действия, поэтому применяйте эти правила для их именования соответственно:
Начните имя с глагола: Добавьте контекст, если это необходимо (например, ПолучитьНаправление, НайтиЦель и т.д.)
Используйте camel case для параметров: Форматируйте параметры, передаваемые в метод, как локальные переменные.
Методы, возвращающие bool, должны задавать вопросы: Подобно самим булевым переменным, префиксируйте методы глаголом, если они возвращают условие истинности или ложности. Это формулирует их в виде вопроса (например, ИграЗавершена, НачалсяХод).
Примечание: Термины "функция" и "метод" часто используются взаимозаменяемо в разработке Unity. Однако, поскольку вы не можете написать функцию, не включив ее в класс в C#, "метод" является правильным термином.
// EXAMPLE: Methods start with a verb.
public void SetInitialPosition(float x, float y, float z)
{
transform.position = new Vector3(x, y, z);
}
// EXAMPLE: Methods ask a question when they return bool.
public bool IsNewPosition(Vector3 currentPosition)
{
return (transform.position == newPosition);
}
События и обработчики событий
События в C# реализуют шаблон наблюдателя. Этот шаблон проектирования программного обеспечения определяет отношения, в которых один объект, субъект (или издатель), может уведомлять список зависимых объектов, называемых наблюдателями (или подписчиками). Таким образом, субъект может транслировать изменения состояния своим наблюдателям, не связывая тесно вовлеченные объекты.
Существуют несколько схем именования для событий и их связанных методов в субъекте и наблюдателях. Попробуйте практики в следующих разделах.
Используйте глаголы
Назовите событие глагольной фразой. Обязательно выберите такую, которая точно передает изменение состояния.
Используйте настоящее или прошедшее причастие, чтобы указать состояние событий до или после. Например, укажите "ОткрытиеДвери" для события перед открытием двери и "ДверьОткрыта" для события после.
Используйте System.Action
Используйте делегат System.Action для событий. В большинстве случаев делегат Action может обрабатывать события, необходимые для игрового процесса.
Вы можете передать до 16 входных параметров разных типов с возвращаемым типом void. Использование предопределенного делегата экономит код.
Примечание: Вы также можете использовать делегаты EventHandler или EventHandler. Согласуйте в команде, как каждый должен реализовывать события.
// EXAMPLE: Events
// using System.Action delegate
public event Action OpeningDoor; // event before
public event Action DoorOpened; // event after
public event Action<int> PointsScored;
public event Action<CustomEventArgs> ThingHappened;
Префикс метода с "On"
Префикс метода вызова события (в субъекте) должен быть «On». Субъект, который вызывает событие, обычно делает это из метода с префиксом «On» (например, «OnOpeningDoor» или «OnDoorOpened»).
// raises the Event if you have subscribers
public void OnDoorOpened()
{
DoorOpened?.Invoke();
}
public void OnPointsScored(int points)
{
PointsScored?.Invoke(points);
}
Префикс с именем субъекта и подчеркиванием
Префикс метода обработки события (в наблюдателе) должен содержать имя субъекта и символ подчеркивания (_). Если субъект называется «GameEvents», ваши наблюдатели могут иметь метод под названием «GameEvents_OpeningDoor» или «GameEvents_DoorOpened».
Решите, какую схему именования использовать вашей команде, и реализуйте эти правила в вашем руководстве по стилю.
Примечание: Этот «метод обработки событий» не следует путать с делегатом EventHandler.
Используйте EventArgs осторожно
Создавайте пользовательские EventArgs только в случае необходимости. Если вам нужно передать пользовательские данные в ваше событие, создайте новый тип EventArgs, унаследованный от System.EventArgs или от пользовательской структуры.
// define an EventArgs if needed
// EXAMPLE: Read-only, custom struct used to pass an ID and Color
public struct CustomEventArgs
{
public int ObjectID { get; }
public Color Color { get; }
public CustomEventArgs(int objectId, Color color)
{
this.ObjectID = objectId;
this.Color = color;
}
}
Пространства имен
Используйте namespaces, чтобы гарантировать, что ваши классы, интерфейсы, перечисления и т. д. не конфликтуют с уже существующими из других пространств имен или глобального пространства имен. Пространства имен также могут предотвратить конфликты с активами третьих сторон из Unity Asset Store или другими тестовыми сценами, которые не будут частью финальной версии проекта.
При применении пространств имен:
Используйте PascalCase без специальных символов или подчеркиваний.
Добавьте директиву using в верхней части файла, чтобы избежать повторного ввода префикса пространства имен.
Создавайте также подпространства имен. Используйте оператор точки (.) для разделения уровней имен, позволяя вам организовать ваши скрипты в иерархические категории. Например, вы можете создать «MyApplication.GameFlow», «MyApplication.AI», «MyApplication.UI» и так далее, чтобы хранить различные логические компоненты вашей игры.
namespace Enemy
{
public class Controller1 : MonoBehaviour
{
...
}
public class Controller2 : MonoBehaviour
{
...
}
}
Префиксы
В коде эти классы называются Враг.Контроллер1 и Враг.Контроллер2, соответственно. Добавьте строку using, чтобы избежать повторного ввода префикса (например, using Враг;).
Когда компилятор находит имена классов Контроллер1 и Контроллер2, он понимает, что вы имеете в виду Враг.Контроллер1 и Враг.Контроллер2.
Если скрипт должен ссылаться на классы с одинаковыми именами из разных пространств имен, используйте префикс для их различия. Например, если у вас есть классы Контроллер1 и Контроллер2 в пространстве имен Игрок, вы можете записать Игрок.Контроллер1 и Игрок.Контроллер2, чтобы избежать конфликтов. В противном случае компилятор сообщит об ошибке.
Получите больше советов по стилю кода
Узнайте больше о общем форматировании здесь или ознакомьтесь с полной электронной книгой. Вы также можете ознакомиться с нашим примером руководства по стилю кода.