26 listopada 2025

Leaked instances

Znalazłem przyczynę wyciekających (okrutnie) instancji Node .... ale nie żebym od razu je wszystkie poprawił, co to to nie.

Wyciekające węzły.


Kłopotem jest to, że w ramach list rozwijalnych montuję pod poszczególnymi opcjami dodatkowe informacje w ramach klas c# zwane metadata. Żeby klasy mogły trafić do takiego typowo godotowego miejsca muszą rozszerzać typ Node ponieważ przez instrukcję SetItemMetadata(index,metadata) mogę dodać tylko coś co jest widoczne w godot i rozszerza typ Variant

Poniżej przykładowa instrukcja dodania metadanych podczas wypełniania listy rozwijalnej OptionButton dla tarcz

ShieldSelect.GetOptionButton().SetItemMetadata(index, metadata);

Klasa dodana jako metadata to dane pancerza. W tym przypadku pierwszym parametrem jest definicja tarczy z jsona, Drugim parametrem jest grupa, do której ta tarcza należy.

 var metadata = new ArmourMetadata(shield, shieldGroup.Key);

Ważna jest jednak definicja klasy ArmourMetadata a nie to co trzyma...


    public partial class ArmourMetadata : Node <-- to te nody najczęściem mi leakują
    {...pola klasy teraz nie są ważne...}

Jak widać rozszerzamy typ Node.

Jak to naprawiać

Ze względu na to, że część list rozwijalnych muszę czyścić i wypełniać na nowo per losowana postać, np. w przypadku broni gdzie chcę na liście oznaczyć, do których broni postać ma preferencyjne bonusy musze listy czyścić i wypełniać ponownie. Tworząc nowe węzły w drzewie...

Nie wystarczy wtedy przeiterować przez kolekcję dzieci dla OptionButtrona jak niżej

foreach (Node child in mentalContainer.GetChildren())
{ reszta kodu z usuwaniem dzieci }

i zrobić na poszczególnych dzieciach child.QueeFree() bo to nie zrzuca metadanych. Potrzeba oddzielnej iteracji po kolekcji metadanych i dodatkowe ich zrzucenie.

Stąd powstała metoda zrzucająca metadane zawarte pod poszczególnymi opcjami

  public void ClearOptionsMetadata()
        {
            for (int i = optionButton.GetItemCount() - 1; i >= 0; i--)
            {
//tu pobieramy metadane
                Variant metadata = optionButton.GetItemMetadata(i);

                if (metadata.VariantType == Variant.Type.Object)
                {
                    Node node = metadata.As<Node>();
                    if (node.IsInsideTree())
                    {
//tu zrzucamy jeśli są wezłem w drzewie
                        node.QueueFree();
                    }
                }
                optionButton.RemoveItem(i);
            }
        }

Podejrzewam, że będę musiał wywołać tę metodę na jakimś ogólnym Dispose() dla obiektów...

Brak komentarzy:

Prześlij komentarz

Tu możesz wstawić swój komentarz