+1 vote

I've noticed memory leaks in my game - according to the Profiler, both Static and Dynamic memory continually increase until eventually crashing. Most of my code is in C#.

I've narrowed down at least the Dynamic leak to where I'm creating a ConcavePolygonShape and then calling SetFaces() on it with an array of vertices. If this is commented out, no Dynamic leak (although Static still climbs).

I've created a small test case to illustrate. Two scripts, one C# and one GDScript, both doing exactly the same thing, which is to create a new ConcavePolygonShape and populate via SetFaces() every call to _Process(). The GDScript version has flat Static memory and Object count and zero Dynamic, the C# version has Static and Dynamic memory and Object count all continually climbing. If I comment out the SetFaces() call in the C# version, Dynamic stays zero but Static and Object count still climb. If you increase the number of vertices, the leak gets larger faster (so seems proportional to number of vertices).

ConcavePolygonShape is not a Node but is held via a Reference as I understand, so should be ref-counted and disposed automatically once all references are gone (i.e. at the end of each _Process() call as I don't hold the ref anywhere).

What's going on? I'm leaning towards a leak bug in the C# godot stuff at the moment, but have I missed something obvious?

Seems very similar to Profiler Question, Memory leak C#?.

Scripts below, attach to a Spatial node in an empty project (switch between the GDScript and C# scripts to see the different behavior).

GDScript:

extends Spatial

func _ready():
    pass

func _process(delta):
    var collisionShapeFaces = ConcavePolygonShape.new()
    var numVerts = 30
    var vertices = []
    for i in range(0, numVerts, 3):
        vertices.append(Vector3(i, 0, 0))
        vertices.append(Vector3(i, 1, 0))
        vertices.append(Vector3(i, 0, 1))
    collisionShapeFaces.set_faces(vertices)

C#:

using Godot;
using System;

public class ShapeLeak : Spatial
{
    public override void _Ready()
    {

    }

    public override void _Process(float delta)
    {
        Shape collisionShapeFaces = new ConcavePolygonShape();
        int numVerts = 30;
        Vector3[] vertices = new Vector3[numVerts];
        for (int i = 0; i < numVerts; i+=3)
        {
            vertices[i] = new Vector3(i, 0, 0);
            vertices[i+1] = new Vector3(i, 1, 0);
            vertices[i+2] = new Vector3(i, 0, 1);
        }

        // // SetFaces() is causing Dynamic Memory Leak, look in Debugger->Monitors Static & Dynamic memory
        // // Try commenting out SetFaces() below to see the Dynamic then stay flat
        ((ConcavePolygonShape)collisionShapeFaces).SetFaces(vertices);

        // // Even with SetFaces() commented out, Static (& object count) steadily increases, in contrast
        // // to the GDScript version of this script where Static and Object count stay flat and Dynamic is zero
    }
}
in Engine by (24 points)

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.