reckfellENGINE

Отладка C#: выбрать подходящий инструмент

Запускаемый пример и границы Output, Remote Inspector, Profiler и управляемого отладчика.

На этой странице

Начните с симптома

СимптомИнструмент и результат
Проект не собираетсяВывод dotnet build; исправьте первую ошибку
Неправильный результат командыOutput, входы и результат операции
Не тот объект или значение свойстваУдалённое дерево и Inspector работающего приложения
Долгий кадрМетрики кадра; затем измерение конкретной нагрузки
Рост памятиПовторяемый сценарий и отдельный учёт нативных объектов/C#-памяти
Нужны C# locals или пошаговое выполнениеОтдельно настроенный управляемый отладчик

В Reckfell 1.0.0 передача ошибок C# и свойств объекта через удалённую диагностику работает. Это не равнозначно полной поддержке управляемых breakpoint, locals и watches во встроенной панели. Встроенный профиль методов C# здесь также не предоставляется.

Запустить проверочный уровень

Нужен C#-проект с Reckfell.NET.Sdk 1.0.0 и net10.0.

  1. Сохраните все четыре файла ниже в проект с точными именами.
  2. Выполните dotnet build.
  3. Создайте уровень с корневым Entity, прикрепите DiagnosticsExample.cs и сохраните как diagnostics.rscene.
  4. Запустите уровень. В Output ожидается DIAGNOSTICS checksum=8386560; lifetime=True; ok=True.

Строки MEASURE и MEMORY зависят от машины и запуска. Их числа не являются нормативом производительности. В работающем дереве найдите DiagnosticsExample/InspectionTarget: DiagnosticToken равен 424242. При запуске отдельного уровня имя корня может отличаться; ребёнок называется InspectionTarget.

DebugInspectionTarget.cs
C#
using Reckfell;

public partial class DebugInspectionTarget : Entity
{
    [Export] public int DiagnosticToken { get; set; } = 424242;
}
WorkMeasurement.cs
C#
using System;
using System.Diagnostics;

public readonly record struct WorkMeasurement(double Milliseconds, long AllocatedBytes, long Checksum)
{
    public static WorkMeasurement Run(int iterations)
    {
        if (iterations < 0 || iterations > 10_000_000)
            throw new ArgumentOutOfRangeException(nameof(iterations));
        long before = GC.GetAllocatedBytesForCurrentThread();
        long start = Stopwatch.GetTimestamp();
        long checksum = 0;
        for (int i = 0; i < iterations; i++) checksum += i;
        double elapsed = Stopwatch.GetElapsedTime(start).TotalMilliseconds;
        long allocated = GC.GetAllocatedBytesForCurrentThread() - before;
        return new WorkMeasurement(elapsed, allocated, checksum);
    }
}
ObjectLifetimeProbe.cs
C#
using System;
using System.Collections.Generic;
using Reckfell;

public static class ObjectLifetimeProbe
{
    public static bool Run()
    {
        var retained = new List<Entity>();
        var parent = new Entity();
        var child = new Entity();
        retained.Add(child);
        parent.AddChild(child);
        parent.RemoveChild(child);
        parent.Free();
        bool detachedSurvived = ReckfellObject.IsInstanceValid(child);
        child.Free();
        bool wrapperOutlivedNative = retained[0] is not null &&
            !ReckfellObject.IsInstanceValid(retained[0]);
        retained.Clear();
        return detachedSurvived && wrapperOutlivedNative;
    }

    public static void PrintSnapshot()
    {
        double objects = Performance.GetMonitor(Performance.Monitor.ObjectCount);
        double entities = Performance.GetMonitor(Performance.Monitor.ObjectNodeCount);
        double orphans = Performance.GetMonitor(Performance.Monitor.ObjectOrphanNodeCount);
        long managed = GC.GetTotalMemory(false);
        ReckfellApi.Print($"MEMORY objects={objects}; entitiesInTree={entities}; outsideTree={orphans}; managedApproxBytes={managed}");
    }
}
DiagnosticsExample.cs
C#
using System.Globalization;
using Reckfell;

public partial class DiagnosticsExample : Entity
{
    public bool Succeeded { get; private set; }

    public override void _Ready()
    {
        var target = new DebugInspectionTarget { Name = "InspectionTarget" };
        AddChild(target);
        _ = WorkMeasurement.Run(64);
        WorkMeasurement measured = WorkMeasurement.Run(4096);
        bool lifetime = ObjectLifetimeProbe.Run();
        Succeeded = measured.Checksum == 8386560 && lifetime;
        ReckfellApi.Print($"DIAGNOSTICS checksum={measured.Checksum}; lifetime={lifetime}; ok={Succeeded}");
        ReckfellApi.Print("MEASURE ms=" + measured.Milliseconds.ToString("F4", CultureInfo.InvariantCulture) +
            "; currentThreadAllocatedBytes=" + measured.AllocatedBytes);
        ObjectLifetimeProbe.PrintSnapshot();
    }
}

Сохранить воспроизводимость

Запишите версию движка, сборку Debug/ExportRelease, платформу, шаги до сбоя и первую ошибку. Меняйте одну причину за раз. Для журнала используйте настройки логирования, а не снимок последней строки без контекста.

Панель диагностики · Измерить C# · Время жизни и память

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.