reckfellENGINE

Groups: find objects and call a shared method

Live members, CallGroup, Deferred/Unique and saved membership without implying type safety.

On this page

Run a group call

Add GroupTarget2D.cs and GroupDemo2D.cs to a 1.0.0 C# project. Attach GroupDemo2D to an Entity2D in a separate level, set a 640×420 viewport, build and run with F6. The button lowers three receivers from 100 HP to 90. They belong to doc_damageables.

One group call reduced the health of three receivers

GroupTarget2D.cs
C#
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
C#
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);
    }
}

A group is a membership tag, not a C# base class, ECS or a guarantee that a method exists. Here every member intentionally implements ApplyDamage(int). For a required typed contract, use explicit references/interfaces and check types instead of treating a group name as compiler validation.

Membership and the active tree

AddToGroup works before AddChild. IsInGroup is already true, but GetEntitiesInGroup/GetEntityCountInGroup query active EntityTree members. RemoveChild removes an object from that query while retaining its tag; reentry registers membership again. RemoveFromGroup explicitly removes the tag. A global editor group description does not load every asset file using the name.

Saving membership in PackedEntity needs persistent: true and correct Owner for the saved branch. Default membership is runtime-only. Repeated AddToGroup on an existing member does not update its persistent flag: set it on first addition or explicitly remove and re-add the tag.

Immediate or deferred

CallGroup invokes now. CallGroupFlags with Deferred queues calls; do not expect updated values immediately after requesting them. Reverse reverses tree traversal. Do not substitute traversal order for an explicit sequence of critical gameplay operations.

Unique works with Deferred. Repeated requests with the same group + method coalesce until queue flushing; different arguments do not form a different key. The check requests damage 3 and 9 and gets one call using the first value, 3. Unique without Deferred does not deduplicate immediate calls. In the checked build the Unique queue flushes in ordinary order without retaining Reverse; do not use that combination for a critical action sequence.

Pause and ProcessMode.Disabled do not block direct CallGroup or NotifyGroup calls. If an action must not mutate gameplay while paused, enforce that rule in its contract. NotifyGroup sends a code to _Notification; the example separately handles RefreshNotification.

The fixture verifies order/reverse traversal, disabled members, deferred coalescing, exit/reentry, saved tags and native deletion. A group establishes neither network authority, thread safety nor cheap large-world processing.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.