Группы: найти объекты и вызвать общий метод
Живые участники, CallGroup, Deferred/Unique и сохранение членства без ложного обещания типобезопасности.
Запустить групповой вызов
Добавьте GroupTarget2D.cs и GroupDemo2D.cs в C#-проект 1.0.0. Прикрепите GroupDemo2D к Entity2D отдельного уровня, задайте viewport 640×420, соберите и запустите F6. Кнопка уменьшает HP трёх получателей со 100 до 90. Они состоят в doc_damageables.
GroupTarget2D.cs
using System.Collections.Generic;
using Reckfell;
public partial class GroupTarget2D : Entity2D
{
public const int RefreshNotification = 10001;
public int Health { get; private set; } = 100;
public int DamageCalls { get; private set; }
public int RefreshCalls { get; private set; }
public List<string>? Calls { get; set; }
public void ApplyDamage(int amount)
{
if (amount <= 0) return;
Health = Mathf.Max(0, Health - amount);
DamageCalls++;
Calls?.Add(Name.ToString());
QueueRedraw();
}
public override void _Notification(int what)
{
if (what == RefreshNotification) RefreshCalls++;
}
public override void _Draw()
{
DrawRect(new Rect2(0, 0, 140, 90), new Color(.08f, .09f, .11f));
DrawRect(new Rect2(10, 56, 120 * Health / 100f, 12), new Color(.25f, .45f, 1));
DrawString(ThemeDB.FallbackFont, new Vector2(10, 32), Name + " · HP " + Health, fontSize: 18);
}
}GroupDemo2D.cs
using Reckfell;
public partial class GroupDemo2D : Entity2D
{
public const string DamageGroup = "doc_damageables";
public override void _Ready()
{
AddChild(new Label { Position = new Vector2(28, 24), Text = TranslationServer.GetLocale().StartsWith("ru")
? "Группа: один вызов, несколько получателей"
: "Group: one call, several receivers" });
for (int i = 0; i < 3; i++)
{
var target = new GroupTarget2D { Name = "Target" + (i + 1), Position = new Vector2(60 + 180 * i, 180) };
target.AddToGroup(DamageGroup);
AddChild(target);
}
var button = new Button { Position = new Vector2(28, 82), Text = TranslationServer.GetLocale().StartsWith("ru") ? "Урон всем: 10" : "Damage all: 10" };
button.Pressed += () => GetTree().CallGroup(DamageGroup, GroupTarget2D.MethodName.ApplyDamage, 10);
AddChild(button);
}
}Группа — метка членства, не базовый C#-класс, не ECS и не гарантия наличия метода. В примере все участники намеренно реализуют ApplyDamage(int). Для обязательного типового контракта используйте явные ссылки/интерфейсы и проверяйте типы, а не считайте имя группы проверкой компилятора.
Членство и активное дерево
AddToGroup можно вызвать до AddChild. IsInGroup уже будет true, но GetEntitiesInGroup/GetEntityCountInGroup находят участников активного EntityTree. RemoveChild исключает объект из активной выборки, сохраняя его метку; при возвращении членство регистрируется снова. RemoveFromGroup удаляет метку явно. Глобальное описание группы в редакторе не загружает все файлы, где это имя используется.
Для записи членства в PackedEntity нужен persistent: true и корректный Owner сохраняемой ветки. По умолчанию членство runtime и не сохраняется. Повторный AddToGroup существующего участника не обновляет его persistent-флаг: задайте его при первом добавлении либо явно удалите и добавьте метку заново.
Немедленно или отложенно
CallGroup выполняет вызовы сейчас. CallGroupFlags с Deferred откладывает их; не ожидайте обновлённое значение сразу после запроса. Reverse меняет порядок обхода дерева. Порядок обхода не стоит использовать вместо явной последовательности критических игровых операций.
Unique действует вместе с Deferred. Повторные запросы одинаковых group + method объединяются до сброса очереди; различающиеся аргументы не создают отдельный ключ. В проверке запросы урона 3 и 9 дают один вызов с первым значением 3. Unique без Deferred не устраняет повторные немедленные вызовы. В проверенной сборке Unique-очередь сбрасывается в обычном порядке и не сохраняет Reverse; не используйте эту комбинацию для критической последовательности действий.
Пауза и ProcessMode.Disabled не блокируют прямой CallGroup или NotifyGroup. Если метод не должен менять игровое состояние при паузе, проверьте это в самом контракте действия. NotifyGroup передаёт код в _Notification; пример отдельно обрабатывает RefreshNotification.
В стенде проверены порядок, обратный обход, отключённые участники, отложенное объединение, выход/возврат, сохранение меток и native-удаление. Группа не задаёт сетевую авторитетность, потокобезопасность или дешёвую обработку большого мира.