You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/asset-system/README.md
+17-36Lines changed: 17 additions & 36 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,8 @@
1
-
# Asset System — Contributor Overview
1
+
# Asset System — Overview
2
2
3
-
This document explains the Stride asset system for engine contributors. It covers the complete
4
-
pipeline from design-time authoring through build compilation to runtime loading, and shows
5
-
how all parts are wired together.
3
+
This document explains the Stride asset system. It covers the complete pipeline from design-time authoring through build compilation to runtime loading, and shows how all parts are wired together.
6
4
7
-
> **For game-project custom assets** (not engine contributions), the same pipeline applies
8
-
> with minor differences noted in each spoke file. See also the external guide:
> **For game-project custom assets** (not engine contributions), the same pipeline applies with minor differences noted in each spoke file. See also the external guide: [Creating custom assets](https://doc.stride3d.net/latest/en/manual/scripts/custom-assets.html).
10
6
11
7
## The Three-Phase Pipeline
12
8
@@ -24,15 +20,11 @@ flowchart LR
24
20
D -->|"loaded into"| E
25
21
```
26
22
27
-
**Design time:** The author edits asset properties in GameStudio. Properties are persisted to a
28
-
`.sdXXX` YAML file. The file is deserialized into an instance of the asset class.
23
+
**Design time:** The author edits asset properties in GameStudio. Properties are persisted to a `.sdXXX` YAML file. The file is deserialized into an instance of the asset class.
29
24
30
-
**Build time:** The build pipeline invokes the compiler registered for the asset type. The
31
-
compiler reads the asset class instance and produces compiled binary content, which is written
32
-
to the content database.
25
+
**Build time:** The build pipeline invokes the compiler registered for the asset type. The compiler reads the asset class instance and produces compiled binary content, which is written to the content database.
33
26
34
-
**Runtime:** The game calls `ContentManager.Load<RuntimeType>(url)`. The engine reads the
35
-
compiled binary and returns a typed instance.
27
+
**Runtime:** The game calls `ContentManager.Load<RuntimeType>(url)`. The engine reads the compiled binary and returns a typed instance.
36
28
37
29
## Assembly Map
38
30
@@ -75,37 +67,26 @@ See [editor.md](editor.md) for implementation details for each tier.
75
67
76
68
## Implementation Checklist
77
69
78
-
Use this checklist when adding a new asset type. Steps marked **optional** are only needed
79
-
in specific circumstances.
70
+
Use this checklist when adding a new asset type. Steps marked **optional** are only needed in specific circumstances.
-[ ]**Asset class** — `[DataContract]`, `[AssetDescription]`; add `[AssetContentType]` and `[AssetFormatVersion]` when the asset has a compiled runtime output → see [asset-class.md](asset-class.md)
76
+
-[ ]**Compiler** — `[AssetCompiler(typeof(%%Asset%%), typeof(AssetCompilationContext))]` on the compiler class; implement the protected `Prepare` override → see [compiler.md](compiler.md)
77
+
-[ ]**Module initializer** — `AssemblyRegistry.Register(...)` in the assembly's `Module.cs` → see [registration.md](registration.md)
91
78
92
79
### Recommended
93
80
94
-
-[ ]**`.sdtpl` template** — adds the asset to the **Add Asset** menu in GameStudio →
95
-
see [registration.md](registration.md#sdtpl-template-files-new-asset-menu)
81
+
-[ ]**`.sdtpl` template** — adds the asset to the **Add Asset** menu in GameStudio → see [registration.md](registration.md#sdtpl-template-files-new-asset-menu)
96
82
97
83
### Conditional
98
84
99
-
-[ ]**`AssetViewModel<T>` (Tier 2)** — only if custom editor commands or display logic is
100
-
needed → see [editor.md](editor.md#tier-2-custom-assetviewmodelt)
101
-
-[ ]**`AssetEditorViewModel` + XAML View (Tier 3)** — only if a dedicated editor panel is
102
-
needed → see [editor.md](editor.md#tier-3-full-custom-editor)
103
-
-[ ]**`GetInputFiles` override** — only if the compiler reads external files →
104
-
see [compiler.md](compiler.md#declare-external-file-dependencies-getinputfiles)
105
-
-[ ]**`GetInputTypes` override** — only if compilation depends on another asset being
106
-
compiled first → see [compiler.md](compiler.md#declare-asset-dependencies-getinputtypes)
107
-
-[ ]**Version upgrader** — only when bumping `[AssetFormatVersion]` on an existing asset →
108
-
see [asset-class.md](asset-class.md#versioning-and-upgraders)
85
+
-[ ]**`AssetViewModel<T>` (Tier 2)** — only if custom editor commands or display logic is needed → see [editor.md](editor.md#tier-2-custom-assetviewmodelt)
86
+
-[ ]**`AssetEditorViewModel` + XAML View (Tier 3)** — only if a dedicated editor panel is needed → see [editor.md](editor.md#tier-3-full-custom-editor)
87
+
-[ ]**`GetInputFiles` override** — only if the compiler reads external files → see [compiler.md](compiler.md#declare-external-file-dependencies-getinputfiles)
88
+
-[ ]**`GetInputTypes` override** — only if compilation depends on another asset being compiled first → see [compiler.md](compiler.md#declare-asset-dependencies-getinputtypes)
89
+
-[ ]**Version upgrader** — only when bumping `[AssetFormatVersion]` on an existing asset → see [asset-class.md](asset-class.md#versioning-and-upgraders)
Copy file name to clipboardExpand all lines: docs/asset-system/asset-class.md
+2-5Lines changed: 2 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,9 +13,7 @@ The asset class is the design-time representation of an asset. An instance is se
13
13
|`AssetComposite`| The asset is composed of named sub-parts that can be individually referenced and overridden in derived assets. |`SceneAsset`, `PrefabAsset`|
14
14
|`AssetCompositeHierarchy<TAssetPartDesign, TAssetPart>`| Like `AssetComposite` but with a parent/child hierarchy among parts. Used for scenes and prefabs. Prefer `AssetComposite` unless you need a tree structure. |`SceneAsset`, `PrefabAsset`|
15
15
16
-
> **Decision:** Start with `Asset`. Upgrade to `AssetWithSource` if the asset's primary content
17
-
> comes from a file on disk that Stride did not produce. Use `AssetComposite` only if your asset
18
-
> must support per-part archetype inheritance.
16
+
> **Decision:** Start with `Asset`. Upgrade to `AssetWithSource` if the asset's primary content comes from a file on disk that Stride did not produce. Use `AssetComposite` only if your asset must support per-part archetype inheritance.
19
17
20
18
## Required Attributes
21
19
@@ -105,5 +103,4 @@ public sealed class %%AssetName%%Asset : Asset // or AssetWithSource
105
103
```
106
104
107
105
> [!NOTE] Game projects
108
-
> Replace `StrideConfig.PackageName` with a string literal matching your game's package name
109
-
> (e.g. `"MyGame"`). The rest of the pattern is identical.
106
+
> Replace `StrideConfig.PackageName` with a string literal matching your game's package name (e.g. `"MyGame"`). The rest of the pattern is identical.
Copy file name to clipboardExpand all lines: docs/asset-system/compiler.md
+17-51Lines changed: 17 additions & 51 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,10 +2,7 @@
2
2
3
3
## Role
4
4
5
-
The compiler transforms a design-time `Asset` instance into compiled runtime content stored in
6
-
the content database. It is invoked during the game build and by the editor for live preview. A
7
-
compiler is registered by decorating the compiler class with `[AssetCompiler]`. The compiler runs
8
-
on a background thread and must not access any editor UI state.
5
+
The compiler transforms a design-time `Asset` instance into compiled runtime content stored in the content database. It is invoked during the game build and by the editor for live preview. A compiler is registered by decorating the compiler class with `[AssetCompiler]`. The compiler runs on a background thread and must not access any editor UI state.
9
6
10
7
## Register the Compiler
11
8
@@ -14,15 +11,11 @@ on a background thread and must not access any editor UI state.
14
11
public class %%AssetName%%Compiler : AssetCompilerBase { ... }
15
12
```
16
13
17
-
`AssetCompilationContext` is the standard context for game-asset compilation. Other contexts exist
18
-
for thumbnail generation and template expansion, but `AssetCompilationContext` is always the right
19
-
choice for new engine assets.
14
+
`AssetCompilationContext` is the standard context for game-asset compilation. Other contexts exist for thumbnail generation and template expansion, but `AssetCompilationContext` is always the right choice for new engine assets.
20
15
21
16
## Implement `Prepare`
22
17
23
-
`Prepare` is called once per asset. It must populate `result.BuildSteps` with one or more
24
-
`AssetCommand<T>` instances that do the actual work. The commands are executed later, possibly in
25
-
parallel with commands from other assets.
18
+
`Prepare` is called once per asset. It must populate `result.BuildSteps` with one or more `AssetCommand<T>` instances that do the actual work. The commands are executed later, possibly in parallel with commands from other assets.
`targetUrlInStorage` is the URL under which the compiled output must be saved in the content
41
-
database. Pass it to `ContentManager.Save` inside `DoCommandOverride`.
33
+
`targetUrlInStorage` is the URL under which the compiled output must be saved in the content database. Pass it to `ContentManager.Save` inside `DoCommandOverride`.
42
34
43
35
## Implement the Build Command
44
36
45
-
The command does the actual compilation work. It extends `AssetCommand<TParameters>` where
46
-
`TParameters` is the asset type (or a dedicated parameters struct for complex conversions).
37
+
The command does the actual compilation work. It extends `AssetCommand<TParameters>` where `TParameters` is the asset type (or a dedicated parameters struct for complex conversions).
47
38
48
39
```csharp
49
40
public class %%AssetName%%Command(string url, %%AssetName%%Asset parameters, IAssetFinder assetFinder)
@@ -65,19 +56,13 @@ public class %%AssetName%%Command(string url, %%AssetName%%Asset parameters, IAs
65
56
}
66
57
```
67
58
68
-
`Parameters` is the typed asset instance passed from `Prepare`. `Url` is the
69
-
`targetUrlInStorage` value passed to the constructor.
70
-
`MicrothreadLocalDatabases.ProviderService` provides the content database to the
71
-
`ContentManager` on the compiler thread.
59
+
`Parameters` is the typed asset instance passed from `Prepare`. `Url` is the `targetUrlInStorage` value passed to the constructor. `MicrothreadLocalDatabases.ProviderService` provides the content database to the `ContentManager` on the compiler thread.
Override `GetInputFiles` when the compiler reads external files (e.g. a `.png` or `.fbx`). This
76
-
allows the build system to detect changes and invalidate the cache correctly.
63
+
Override `GetInputFiles` when the compiler reads external files (e.g. a `.png` or `.fbx`). This allows the build system to detect changes and invalidate the cache correctly.
77
64
78
-
The pattern requires **two parts**: overriding `GetInputFiles` on the compiler class, and wiring
79
-
it to the build command via `InputFilesGetter` in `Prepare`. Without the wiring, the build cache
80
-
will never invalidate when source files change.
65
+
The pattern requires **two parts**: overriding `GetInputFiles` on the compiler class, and wiring it to the build command via `InputFilesGetter` in `Prepare`. Without the wiring, the build cache will never invalidate when source files change.
81
66
82
67
**Step 1 — Override `GetInputFiles` on the compiler:**
83
68
@@ -90,9 +75,7 @@ public override IEnumerable<ObjectUrl> GetInputFiles(AssetItem assetItem)
90
75
}
91
76
```
92
77
93
-
Check that `asset.Source` is not null or empty before calling `GetAbsolutePath` — `GetAbsolutePath`
94
-
throws an `ArgumentException` if passed a null or empty path. `GetAbsolutePath` is a helper on
95
-
`AssetCompilerBase` that resolves a `UFile` source path relative to the asset's location on disk.
78
+
Check that `asset.Source` is not null or empty before calling `GetAbsolutePath` — `GetAbsolutePath` throws an `ArgumentException` if passed a null or empty path. `GetAbsolutePath` is a helper on `AssetCompilerBase` that resolves a `UFile` source path relative to the asset's location on disk.
`InputFilesGetter` is a `Func<IEnumerable<ObjectUrl>>` delegate on `Command`. The build engine
106
-
calls it when computing the command hash; without it, file changes are invisible to the cache.
88
+
`InputFilesGetter` is a `Func<IEnumerable<ObjectUrl>>` delegate on `Command`. The build engine calls it when computing the command hash; without it, file changes are invisible to the cache.
107
89
108
90
> [!NOTE]
109
-
> Alternatively, override `GetInputFiles()` (no parameters) directly on the command class itself.
110
-
> `Command.GetInputFiles()` calls `InputFilesGetter` by default, but you can override it instead
111
-
> to keep the logic self-contained on the command — this avoids the delegate wiring entirely.
112
-
> `TextureConvertCommand` uses this approach.
91
+
> Alternatively, override `GetInputFiles()` (no parameters) directly on the command class itself. `Command.GetInputFiles()` calls `InputFilesGetter` by default, but you can override it instead to keep the logic self-contained on the command — this avoids the delegate wiring entirely. `TextureConvertCommand` uses this approach.
113
92
114
93
## Declare Asset Dependencies (`GetInputTypes`)
115
94
116
-
Override `GetInputTypes` when the compiler needs another asset to be compiled first, or needs to
117
-
read another asset's compiled output during compilation.
95
+
Override `GetInputTypes` when the compiler needs another asset to be compiled first, or needs to read another asset's compiled output during compilation.
@@ -135,30 +113,18 @@ public override IEnumerable<BuildDependencyInfo> GetInputTypes(AssetItem assetIt
135
113
|`CompileAsset`| The uncompiled `Asset` object of the dependency is read during compilation. |
136
114
|`CompileContent`| The compiled output of the dependency is read during compilation. |
137
115
138
-
Use `CompileAsset` when you only need to read the asset class properties — this is cheap and
139
-
imposes no hard build-order constraint beyond "loaded". Use `CompileContent` when you need the
140
-
compiled binary output, which requires the dependency to be fully compiled first. Use `Runtime`
141
-
for runtime references that are embedded in the compiled output, not accessed at compile time.
116
+
Use `CompileAsset` when you only need to read the asset class properties — this is cheap and imposes no hard build-order constraint beyond "loaded". Use `CompileContent` when you need the compiled binary output, which requires the dependency to be fully compiled first. Use `Runtime` for runtime references that are embedded in the compiled output, not accessed at compile time.
142
117
143
118
> [!WARNING]
144
-
> Do not create circular dependencies via `GetInputFiles` or `GetInputTypes`. Asset A depending
145
-
> on B while B depends on A will deadlock the build.
119
+
> Do not create circular dependencies via `GetInputFiles` or `GetInputTypes`. Asset A depending on B while B depends on A will deadlock the build.
146
120
147
121
## Assembly Placement
148
122
149
-
Compiler classes live in the same assembly as the asset class. For engine assets in
150
-
`Stride.Assets`, the compiler also lives in `Stride.Assets`. The `[AssetCompiler]` attribute is
151
-
discovered at startup when the assembly is registered with `AssemblyCommonCategories.Assets`.
152
-
Compilers must not reference editor assemblies.
123
+
Compiler classes live in the same assembly as the asset class. For engine assets in `Stride.Assets`, the compiler also lives in `Stride.Assets`. The `[AssetCompiler]` attribute is discovered at startup when the assembly is registered with `AssemblyCommonCategories.Assets`. Compilers must not reference editor assemblies.
153
124
154
125
## Template
155
126
156
-
The `Prepare` method and build command shown above form the complete starting template for a new
157
-
compiler. Copy both blocks, replace `%%AssetName%%` with your asset's PascalCase name, and fill
158
-
in the property mapping inside `DoCommandOverride`.
127
+
The `Prepare` method and build command shown above form the complete starting template for a new compiler. Copy both blocks, replace `%%AssetName%%` with your asset's PascalCase name, and fill in the property mapping inside `DoCommandOverride`.
159
128
160
129
> [!NOTE] Game projects
161
-
> For game-project custom assets, the compiler class lives in the game project itself.
> to the game project's `.csproj` — this brings in the infrastructure that discovers and invokes
164
-
> the compiler; it does not change where the compiler class lives.
130
+
> For game-project custom assets, the compiler class lives in the game project itself. Add `<PackageReference Include="Stride.Core.Assets.CompilerApp" IncludeAssets="build;buildTransitive" />` to the game project's `.csproj` — this brings in the infrastructure that discovers and invokes the compiler; it does not change where the compiler class lives.
0 commit comments