C#: обязательные правила и стиль проекта
Что необходимо генератору и сериализации, а что команда выбирает самостоятельно.
Правила, влияющие на работу
| Правило | Причина |
|---|---|
| partial у класса, наследующего ReckfellObject | Генератор добавляет код API; без partial — RF0001 |
| Имя прикрепляемого класса совпадает с файлом, включая регистр | Генератор связывает скрипт с его путём |
| Export только поддерживаемого члена экземпляра | Static/readonly/неподдерживаемый тип не становятся сохраняемым состоянием |
| EventHandler в конце делегата Signal | Генератор создаёт соответствующее событие; см. руководство по сигналам |
| Стабильные имена экспортированных полей и путей | Их используют сериализованные данные и зависимости уровней |
Переименование экспортированного поля не является миграцией сохранённых значений. Перед массовым переименованием проверьте затронутые .rscene/.rprefab/.rdata и загрузку старых данных. Не редактируйте сгенерированные MethodName/PropertyName: исправляйте исходный член и пересобирайте.
Соглашения для читаемого кода
В этих примерах классы, методы и свойства имеют PascalCase; private-поле — _camelCase; локальные переменные — camelCase. Это соглашение, а не отдельная архитектура движка. Не переименовывайте обязательные callbacks вроде _Ready по правилу обычных методов.
Числа с единицами называйте по смыслу: delta — время callback, Damage — величина урона, Ammo — количество. Условие отказа ставьте перед изменением состояния; TryFire не тратит патрон при неверных настройках.
ExportedWeapon.cs
using Reckfell;
public partial class ExportedWeapon : Entity
{
[Signal] public delegate void FiredEventHandler(int damage);
[Export] public ShotSettings? Settings { get; set; }
[Export(PropertyHint.Range, "0,99,1")] private int _ammo = 5;
public int Ammo => _ammo;
public int TransientValue { get; set; } = 3;
public bool TryFire()
{
if (_ammo <= 0 || !ReckfellObject.IsInstanceValid(Settings) ||
!Settings!.TryGetDamage(out int damage)) return false;
_ammo--;
EmitSignal(SignalName.Fired, damage);
return true;
}
}Этот компонент использует сгенерированное SignalName.Fired, хранит состояние экземпляра отдельно от Resource-настроек и возвращает bool при ожидаемом отказе. Полный запуск — в примере экспорта.
Обычным helper-классам InventoryLedger и VariantCounter не добавляйте Entity, partial или GlobalClass ради единообразия. Форматирование, порядок using и пространство имён зафиксируйте один раз для своего проекта; отдельная статья не должна менять существующие правила команды.