Instantiate and save an Entity tree
Parent, Owner and PackedEntity; why a child can work at runtime yet disappear after saving.
Parent and Owner have different jobs
Parent defines hierarchy, inherited transforms and child lifetime. AddChild joins that hierarchy. Owner identifies the saved tree to which an Entity belongs. It must be an ancestor; do not assign a root as its own owner.
For an ordinary tree built in code for saving, assign child.Owner = root after AddChild. Temporary gameplay projectiles do not need this merely to run. A nested prefab instance already contains its own Owner scopes; do not overwrite every descendant's owner in one loop.
Verify a saved tree
Add OwnerPackingDemo.cs to a 1.0.0 C# project, attach it to an Entity in a separate test level, build and press F6. Output shows Owner packing: Ok and user:// contains OwnedExample.rprefab. Open the project's user-data directory and inspect the file: Saved is present, Transient is absent. The example overwrites only the specified tutorial file.
OwnerPackingDemo.cs
using Reckfell;
public partial class OwnerPackingDemo : Entity
{
public static Error SaveExample(string path)
{
if (!path.EndsWith(".rprefab") && !path.EndsWith(".rscene")) return Error.InvalidParameter;
var root = new Entity2D { Name = "OwnedExample" };
try
{
var saved = new Entity2D { Name = "Saved", Position = new Vector2(12, 34) };
root.AddChild(saved);
saved.Owner = root;
var transient = new Entity { Name = "Transient" };
root.AddChild(transient);
using var packed = new PackedEntity();
Error error = packed.Pack(root);
return error == Error.Ok ? ResourceSaver.Save(packed, path) : error;
}
finally
{
root.Free();
}
}
public override void _Ready()
{
Error error = SaveExample("user://OwnedExample.rprefab");
ReckfellApi.Print("Owner packing: " + error);
}
}Pack takes a serializable tree snapshot; it does not write a disk file automatically. ResourceSaver.Save runs only after a successful Pack. To load, use ResourceLoader.Load<PackedEntity>, check the result and CanInstantiate, then call Instantiate. The new root is still detached: configure required properties before AddChild.
The fixture frees the original root after Pack, then restores Saved.Position and Owner through a new instance. These are separate Entities. Other Resource references inside a prefab can remain shared: creating Entities does not deep-copy every material and texture.
Diagnose a missing child
| Cause | Action |
|---|---|
| Parent exists but the required Owner is missing | Assign Owner after attaching to its ancestor |
| An intermediate container has no Owner | Check the whole saved branch: Pack can omit it and its descendants |
| The wrong root was packed | Pass the root you intend to restore |
| PackedEntity was saved before modifying objects | Pack again after the modification; it does not track the live tree |
| A nested prefab received an unrelated Owner | Preserve its own structure and change only intended overrides |
PackedEntityState.GetEntityCount counts snapshot entries rather than every descendant expanded from nested prefabs. The level example has three saved entries: one root and two prefab references. Instantiate produces more actual descendants.
Runtime creation and removal
_EnterTree runs on entry and _Ready after children are ready. If an object consumes settings or emits a signal in _Ready, configure it and connect handlers before AddChild. Do not assume _Ready repeats on every entry of a reused object.
QueueFree queues deletion; the reference can still exist until that queue is processed. After release, a C# variable does not guarantee a live native object: check ReckfellObject.IsInstanceValid and do not access a freed Entity. RemoveChild only detaches; it does not free. Someone must retain responsibility for the detached object's lifetime.