reckfellENGINE

Class inheritance and the ClassDB registry

Current-build chains, object creation and class versus tree parent.

On this page

Class inheritance answers “what kind of object is this?” An Entity parent answers “where is this instance in the tree?” A C# script type answers another question again. Keep them separate when choosing a base class, inspecting an object or building an editor tool.

Main native branches

Native branchPurpose
ObjectReflection, properties, signals and object identity; C# wrapper: ReckfellObject.
Object → RefCounted → ResourceReference-counted data/resources, not automatically Entity-tree members.
Object → EntityTree participation and lifecycle; this is not a renderer transform by itself.
Entity → CanvasItem → Entity2D2D transform and canvas hierarchy.
Entity → CanvasItem → ControlInterface/layout branch; Control is not derived from Entity2D.
Entity → Entity3D3D transform branch.

The tested complete Entity2D chain is Entity2D → CanvasItem → Entity → Object. An Entity2D can be a child of a script Entity instance while its class parent remains CanvasItem. Changing GetParent() never changes its inheritance chain.

Native names are the ClassDB names, not necessarily C# wrapper names. The native root is Object; the wrapper is ReckfellObject. GetClass reports the native backing type; GetType describes the managed CLR type. An attached managed script is not automatically registered as a native ClassDB class under its C# class name.

Query the current build

Do not rely on the old static class-tree archive. Available native classes vary with build configuration, platform and loaded extensions. This complete helper queries the running registry:

C#
using System;
using System.Collections.Generic;
using Reckfell;

public static class ObjectRegistry
{
    public static string[] InheritanceChain(StringName type)
    {
        if (!ClassDB.ClassExists(type))
            throw new ArgumentException("Unknown native class.", nameof(type));
        var result = new List<string>();
        string current = type.ToString();
        while (current.Length != 0)
        {
            result.Add(current);
            current = ClassDB.GetParentClass(current).ToString();
        }
        return result.ToArray();
    }

    public static string[] Descendants(StringName type, bool directOnly = false)
    {
        if (!ClassDB.ClassExists(type))
            throw new ArgumentException("Unknown native class.", nameof(type));
        var result = new List<string>();
        foreach (string candidate in ClassDB.GetInheritersFromClass(type))
            if (!directOnly || ClassDB.GetParentClass(candidate).ToString() == type.ToString())
                result.Add(candidate);
        result.Sort(StringComparer.Ordinal);
        return result.ToArray();
    }

    public static ReckfellObject CreateNative(StringName type)
    {
        if (!ClassDB.ClassExists(type))
            throw new ArgumentException("Unknown native class.", nameof(type));
        if (!ClassDB.CanInstantiate(type))
            throw new InvalidOperationException("Class is not instantiable in this context.");
        using Variant value = ClassDB.Instantiate(type);
        return value.AsReckfellObject()
            ?? throw new InvalidOperationException("Native creation failed.");
    }
}

Save as ObjectRegistry.cs. ObjectRegistry.InheritanceChain("Entity2D") returns the native chain. ObjectRegistry.Descendants("Entity", true) filters direct children; false includes indirect descendants. The helper sorts its own result ordinally. GetInheritersFromClass itself means all descendants and excludes the queried base, not just one level.

IsParentClass has a potentially confusing argument order: ClassDB.IsParentClass("Entity2D", "Entity") tests whether Entity is a base of Entity2D. This implementation also returns true for the same class on both sides. GetParentClass returns the immediate native parent; Object has an empty parent name.

Existence is not creation permission

ClassExists checks registration, IsClassExposed checks public exposure, IsClassEnabled checks enabled state, and CanInstantiate checks creator/context availability. They are different tests. CanvasItem exists but is abstract/non-instantiable in the checked build. Editor-only types or extension classes can have additional context requirements.

For normal gameplay, prefer a known typed constructor. CreateNative is useful for tools that deliberately choose a native class. It rejects unknown or non-instantiable names before calling Instantiate. It does not create an arbitrary CLR class, attach a C# script, or return a populated prefab.

The returned object's lifetime belongs to the caller. Free a created Entity/Object when appropriate, or add an Entity to the intended owning tree lifecycle. Dispose/release owned RefCounted wrappers according to their reference-counted lifetime. The helper's temporary Variant is disposed; the native test verifies that the returned RefCounted wrapper remains valid.

Inspect inherited API

ClassGetMethodList, ClassGetPropertyList and ClassGetSignalList describe registered metadata. Use their noInheritance option when you need only declarations of that class; do not infer inheritance from a scene-tree parent. The checked Entity2D method list includes inherited get_instance_id by default and excludes it with noInheritance=true. The bound property position resolves to get_position/set_position. A zero ClassGetMethodArgumentCount does not prove that a zero-argument method exists: this version also returns zero when no matching bound method is found.

These native API names are case-sensitive. A C# wrapper method such as SetPosition is not the native string method name set_position. For instance-specific script properties or dynamically added user signals, inspect the object itself instead of assuming ClassDB contains every managed/runtime declaration.

To choose a base, start from the capability needed: data lifetime, tree lifecycle, 2D transform, UI layout or 3D transform. A class name does not turn the tree into an ECS; this is an object-inheritance model. See Object architecture for binding and ownership details.

The helper and registry/instance distinctions are checked in the installed Windows runtime. The article does not claim one fixed complete class set across every export, extension reload or editor configuration.

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.