# Creating Custom Assets
Stride supports the creation of custom asset types that can be referenced in your scenes as well as reference other assets.
To do so, you must add a reference to the `Stride.Core.Assets` package in your game's `.csproj`:
Here's how it looks like in a default game project:
```xml
net8.0-windows
```
> [!Warning]
> Make sure that the `TargetFrameworks` and all package versions match your current Stride version. The example above shows version 4.2.0.1 for reference.
Inside the same project, create a new csharp file and replace its content with the following:
```cs
using System.Collections.Generic;
using System.Threading.Tasks;
using Stride.Core;
using Stride.Core.Assets;
using Stride.Core.Assets.Compiler;
using Stride.Core.BuildEngine;
using Stride.Core.Serialization;
using Stride.Core.Serialization.Contents;
using Stride.Engine;
using Stride.Engine.Design;
namespace YOUR_GAME_NAMESPACE;
///
/// Runtime representation of the asset, this is the actual class you would use in your scripts
///
[DataContract]
[ContentSerializer(typeof(DataContentSerializerWithReuse))]
// The ReferenceSerializer attribute is required when specifying a DataSerializerGlobal with ReferenceSerializer<>,
// The two of them specifies to the serializers that this class is a runtime Asset
[ReferenceSerializer, DataSerializerGlobal(typeof(ReferenceSerializer), Profile = "Content")]
// The line below ensures that the asset's reference is re-used instead of cloned for all new instances when instantiating prefabs
[DataSerializerGlobal(typeof(CloneSerializer), Profile = "Clone")]
public class YOUR_CLASS
{
// Replace this with whatever you would want this asset to hold at runtime
public List PrefabCollection { get; set; } = new();
}
///
/// Design time and file representation of , you can add content here that won't be included in the build
///
[AssetDescription(FileExtension, AllowArchetype = false)]
[AssetContentType(typeof(YOUR_CLASS))]
[AssetFormatVersion(nameof(YOUR_GAME_NAMESPACE), CurrentVersion, "1.0.0.0")]
public sealed class YOUR_CLASS_ASSET : Asset
{
private const string CurrentVersion = "1.0.0.0";
public const string FileExtension = ".blks";
// Replace this with whatever you would want this asset to have while inside the gamestudio
public List PrefabCollection { get; set; } = new();
}
/// Compiler which transforms your into when building your game
[AssetCompiler(typeof(YOUR_CLASS_ASSET), typeof(AssetCompilationContext))]
public sealed class YOUR_CLASS_COMPILER : AssetCompilerBase
{
protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
{
var asset = (YOUR_CLASS_ASSET)assetItem.Asset;
// you can have many build steps, each one is running an AssetCommand
result.BuildSteps = new AssetBuildStep(assetItem);
result.BuildSteps.Add(new DESIGN_TO_RUNTIME_COMMAND(targetUrlInStorage, asset, assetItem.Package));
}
public override IEnumerable GetInputFiles(AssetItem assetItem)
{
// Yield assets that must be built before this one is built,
// this is for cases were you need to read from a compiled version of an asset to build this one.
// Note that creating cyclic references through this method will cause a deadlock when building
// (e.g.: A is input of B while B is input of A)
// below only for reference purposes, useless in this context
var asset = (YOUR_CLASS_ASSET)assetItem.Asset;
foreach (var block in asset.PrefabCollection)
{
var url = AttachedReferenceManager.GetUrl(block);
if (!string.IsNullOrEmpty(url))
{
yield return new ObjectUrl(UrlType.Content, url);
}
}
}
///
/// An that converts design time asset into runtime asset.
///
public class DESIGN_TO_RUNTIME_COMMAND(string url, YOUR_CLASS_ASSET parameters, IAssetFinder assetFinder)
: AssetCommand(url, parameters, assetFinder)
{
protected override Task DoCommandOverride(ICommandContext commandContext)
{
var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);
var runtimeObject = new YOUR_CLASS{ PrefabCollection = Parameters.PrefabCollection };
assetManager.Save(Url, runtimeObject);
commandContext.Logger.Info($"Saving {nameof(YOUR_CLASS)}: {runtimeObject.PrefabCollection}");
return Task.FromResult(ResultStatus.Successful);
}
}
}
```
> [!Warning]
> Every changes made to the runtime asset will break previously built asset databases, make sure to clean the solution or manually delete the build artifacts stride generates for assets (`YOUR_PROJECT.Windows/obj/stride` and `bin/db`) after changing the class to make sure the asset database is fully rebuilt on the next build.
This takes care of the support for this asset, you could create a `*.blks` file inside your `Assets` directory and fill in the content manually, but might as well do it through the editor ...
## Adding a section for the Add asset menu inside the editor
Create a new directory named `Templates` within your Game's directory, this directory will be used to store your templates.
Inside of that directory, create a new file named after your new asset with the `.sdtpl` extension.

Open the file and paste the following into it
```
!TemplateAssetFactory
Id: 21CC3354-9F0B-4D1F-8242-62D56454B27C
AssetTypeName: YOUR_CLASS_ASSET
Name: THE NAME IN THE EDITOR
Scope: Asset
Description: A DESCRIPTIVE DESCRIPTION OF YOUR ASSET
Group: WHERE THIS WOULD BE CLASSIFIED UNDER IN THE EDITOR
DefaultOutputName: THE DEFAULT FILE NAME
```
Edit the different fields appropriately,
- `Id` must be unique ! There are a couple of services online to generate one if you need to, search for `generate guid online`
- `AssetTypeName` must match the name of the class that inherits from `Asset` (the namespace can be omitted)
Now you have to edit your `*.sdpkg` to include this new template, to do so you just have to add the following lines below your `TemplateFolders:`
```
TemplateFolders:
- Path: !dir Templates
Group: Assets
Files:
- !file Templates/YOUR_TEMPLATE.sdtpl
```
Here's how it looks like when included into a default game `*.sdpkg`:
```
!Package
SerializedVersion: {Assets: 3.1.0.0}
Meta:
Name: MyGame21
Version: 1.0.0
Authors: []
Owners: []
Dependencies: null
AssetFolders:
- Path: !dir Assets
- Path: !dir Effects
ResourceFolders:
- !dir Resources
OutputGroupDirectories: {}
ExplicitFolders: []
Bundles: []
TemplateFolders:
- Path: !dir Templates
Group: Assets
Files:
- !file Templates/YOUR_TEMPLATE.sdtpl
RootAssets: []
```
And you're finally done, have fun !

## See also
* [Best Practice](best-practice.md)