Skip to main content
s&box has two complementary asset concepts: prefabs — serialized GameObject hierarchies you can stamp into a scene at runtime — and resources — typed C# objects backed by files on disk. Understanding both lets you build content-driven games where spawnable actors, materials, models, and sounds are all first-class assets.

Prefabs

A prefab is a .prefab file that stores a complete GameObject hierarchy: the object tree, all component values, and nested prefab references. You create one in the editor by right-clicking a GameObject and choosing Save as prefab. At runtime you load and instantiate the prefab from C#.

Loading a prefab

// Load the cached prefab scene (read-only, do not modify)
var prefabGo = GameObject.GetPrefab( "prefabs/enemies/grunt.prefab" );
GetPrefab calls PrefabFile.Load internally and returns the root GameObject of the cached prefab scene. The returned object is a read-only template — clone it rather than parenting it directly into your scene.

Cloning into the scene

The idiomatic way to spawn a prefab is to use SceneUtility.Instantiate:
var spawnPoint = Transform.World;

// Instantiate the prefab at a world transform
var enemy = SceneUtility.Instantiate(
    ResourceLibrary.Get<PrefabFile>( "prefabs/enemies/grunt.prefab" ),
    spawnPoint
);
Or clone from the cached prefab root directly:
var prefabRoot = GameObject.GetPrefab( "prefabs/enemies/grunt.prefab" );
var instance   = prefabRoot.Clone( Transform.World );
instance.Parent = Game.ActiveScene;

Checking prefab state

The following properties let you query whether a GameObject came from a prefab:
bool isInstance     = go.IsPrefabInstance;      // part of a prefab instance
bool isRoot         = go.IsPrefabInstanceRoot;   // the root object of the instance
string sourceFile   = go.PrefabInstanceSource;   // path to the .prefab file
// Disconnect from the prefab source (becomes a regular GameObject)
go.BreakFromPrefab();

// Pull the latest values from the prefab source file
go.UpdateFromPrefab();
Calling BreakFromPrefab() is irreversible at runtime. Any subsequent changes to the original .prefab file will not be reflected in the broken instance.

Resources

Every asset that lives on disk — materials, models, sounds, scenes, and your own custom data types — is represented by a Resource in C#. The engine provides two layers:
ClassPurpose
ResourceBase for native engine resources (Model, Material, Texture, SoundFile, …)
GameResourceBase for JSON-serialized C# assets you define yourself

The Resource base class

Resource provides the identity and lifetime properties shared by all assets:
Resource r = Material.Load( "materials/dev/white.vmat" );

string path = r.ResourcePath;   // "materials/dev/white.vmat"
string name = r.ResourceName;   // "white"
bool   ok   = r.IsValid;        // false if the asset has been unloaded
Native resources (Model, Material, Texture, SoundFile, AnimationGraph, Shader) are loaded through their own static Load methods:
Model      model   = Model.Load( "models/citizen/citizen.vmdl" );
Material   mat     = Material.Load( "materials/custom/hero.vmat" );
SoundFile  sfx     = SoundFile.Load( "sounds/weapons/shotgun_fire.vsnd" );

GameResource — custom asset types

Inherit GameResource to define your own asset type. Decorate it with [GameResource] to give it a file extension and editor icon. Properties decorated with [Property] are serialized to JSON automatically.
using Sandbox;

[GameResource( "Item Definition", "item", "Defines a collectible item", Icon = "backpack" )]
public sealed class ItemDefinition : GameResource
{
    [Property] public string DisplayName { get; set; }
    [Property] public string Description { get; set; }
    [Property] public Model  PickupModel  { get; set; }
    [Property] public float  HealAmount   { get; set; }

    // Called once after the asset is first loaded from disk
    protected override void PostLoad()
    {
        Log.Info( $"Loaded item: {DisplayName}" );
    }

    // Called when the asset is hot-reloaded in the editor
    protected override void PostReload()
    {
        Log.Info( $"Reloaded item: {DisplayName}" );
    }
}

Loading a GameResource

// Load by path (returns null if not found)
var item = ResourceLibrary.Get<ItemDefinition>( "data/items/medkit.item" );

if ( item is not null )
{
    Log.Info( item.DisplayName );
}

Referencing resources from components

Direct property reference

The simplest approach: use a [Property] of the resource type and assign it in the editor. The asset picker shows a filtered list of compatible files.
public sealed class WeaponComponent : Component
{
    [Property] public Model       WeaponModel  { get; set; }
    [Property] public SoundFile   FireSound    { get; set; }
    [Property] public Material    TracerMat    { get; set; }
    [Property] public ItemDefinition ItemData  { get; set; }
}

FileReference<T>

FileReference<T> is a typed wrapper around a resource path string. Use it when you want to defer loading, store the path without creating a hard dependency, or serialize the path to JSON without loading the asset at deserialization time.
public sealed class SpawnPoint : Component
{
    // Stores the path; asset is loaded on first access
    [Property] public FileReference<PrefabFile> SpawnablePrefab { get; set; }

    protected override void OnUpdate()
    {
        if ( Input.Pressed( "attack1" ) )
        {
            var prefab = SpawnablePrefab.GetAsset();  // loads if not already loaded
            if ( prefab is not null )
                SceneUtility.Instantiate( prefab, Transform.World );
        }
    }
}
FileReference<T> is useful in data-driven designs where a designer needs to assign a prefab or asset at edit time without loading it until it is needed.

Built-in resource types

TypeExtensionDescription
Model.vmdl3D mesh and skeleton
Material.vmatSurface shading parameters
Texture.vtex2D image data
Shader.vfxGPU shader program

Resource lifecycle

GameResource fires two virtual hooks you can override:
MethodWhen it fires
PostLoad()After the resource is first loaded from disk
PostReload()After the resource is hot-reloaded (e.g. a .item file is saved in the editor)
OnDestroy()When the resource is unloaded and removed from ResourceLibrary
protected override void PostLoad()
{
    // Build derived runtime data from serialized properties
    _damageRange = new RangeInt( MinDamage, MaxDamage );
}

protected override void PostReload()
{
    // Invalidate caches when the file changes on disk
    _damageRange = new RangeInt( MinDamage, MaxDamage );
}

Scenes and GameObjects

The hierarchy that prefab instances live inside

Components

Attach behavior and resource references to GameObjects

Build docs developers (and LLMs) love