Prefab instances
Place several instances of one prefab and instantiate it with type validation in C#.
A .rprefab stores a hierarchy with one root. An instance is a separate hierarchy created from it. Two instances of one crate can move independently while still sharing materials or textures.
Place instances in the editor
- Create
Crate.rprefabwith anEntity3Droot and a childMeshInstance3D. AssignBoxMeshtoMesh, then save the file inProps. - Open a level such as
Main.rscene, or a container prefab such asMain.rprefab. Do not placeCrate.rprefabinside itself. - Open the Content resource panel with Ctrl + Space. Drag the file
Props/Crate.rprefabonto the intended parent in the hierarchy. Panel placement depends on the workspace layout; no particular left/bottom position is required. - Repeat, then set the instances' X positions to
-1.5and1.5. Save the document.
This crate only renders. Collisions need a physics body and a shape. If the crates are missing during play, check the level's camera and lighting. If the editor rejects placement for a cyclic dependency, open another document: a prefab cannot contain its own instance directly or through other prefabs.
Source prefab changes reach properties without local overrides. Moving one instance is stored in its containing document. Changing a shared material can affect both objects: duplicate the resource first for an independent material.
Create an instance in code
Save this helper in PrefabFactory.cs; it does not attach to an entity. Call CreateProp() on the main thread with a valid Entity3D parent already inside the tree. For example, use PrefabFactory.CreateProp("asset://Props/Crate.rprefab", this, new Vector3(0, 0, -2)) inside an Entity3D script.
using Reckfell;
public static class PrefabFactory
{
public static Entity3D? CreateProp(
string path, Entity3D parent, Vector3 localPosition)
{
Resource loaded = ResourceLoader.Load(path);
if (loaded is not PackedEntity template || !template.CanInstantiate())
return null;
Entity instance = template.Instantiate();
if (instance is not Entity3D prop)
{
instance?.Free();
return null;
}
prop.Position = localPosition;
parent.AddChild(prop);
return prop;
}
}The method returns the created Entity3D or null. Position is local to the parent and assigned before AddChild(), so _Ready() sees it immediately. If the root is 2D, the newly created, unattached hierarchy is released with Free().
Load() obtains the resource; Instantiate() creates the hierarchy; AddChild() enters it into the tree and starts its lifecycle. Instantiate<Entity3D>() is suitable for a known root type, but a mismatch throws InvalidCastException after creation. InstantiateOrNull<T>() also creates the object before testing its type; it is not a non-instantiating content check.
Deletion and saving
Use QueueFree() for an attached instance: deletion is deferred, so the object may still exist until the end of the frame. The example uses immediate Free() for an unattached object it just created and rejected.
When placing from the resource panel, the editor sets instance ownership for saving in the current document. Runtime instances added with AddChild() are not written to the file automatically: that call does not assign Owner. Owner affects packing the hierarchy and does not replace GetParent(). Both .rscene levels and .rprefab prefabs load as PackedEntity; the resource path determines their role. See creation, world coordinates and deletion.