Assets and the Asset Graph - bryanedds/Nu GitHub Wiki

Assets and the AssetGraph

Nu has a special system for efficiently and conveniently handling assets called the Asset Graph. The Asset Graph is configured in whole by a file named AssetGraph.nuag. This file is included in every new project, and is placed in the same folder as the project’s Program.fs file.

The first thing you might notice about assets in Nu is that they are not built like normal assets via Visual Studio. The Visual Studio projects themselves need to have no knowledge of a game’s assets. Instead, assets are built by a program called Nu.Pipe.exe. Nu.Pipe knows what assets to build by itself consulting the AssetGraph.nuag file. During the build process of a given Nu game project, Nu.Pipe is invoked from the build command line like so –

dotnet "$(MSBuildProjectDirectory)/../../Nu/Nu.Pipe/bin/$(Configuration)/net9.0/Nu.Pipe.dll" "$(MSBuildProjectDirectory)/" "$(MSBuildProjectDirectory)/bin/$(Configuration)/net9.0/" "$(MSBuildProjectDirectory)/refinement/" "False"

Nu.Pipe constructs an AssetGraph object from the project's AssetGraph.nuag file, then uses its API to copy all asset files the nuag file directs it to discover to the project's output directory (depending on the build mode). Additional processing can occur during copy, such as with the ConvertToDds specifier. Note that for speed, Nu.Pipe copies only missing or recently altered assets based on their file time stamps.

Let’s study the structure of the data found inside a new game project’s AssetGraph.nuag file –

[[Default
  [Assets Assets/Default [bmp png psd ttf] [PsdToPng] [Render2d](/bryanedds/Nu/wiki/Assets-Assets/Default-[bmp-png-psd-ttf]-[PsdToPng]-[Render2d)
   [Assets Assets/Default [jpg jpeg tga tif tiff dds] [ConvertToDds] [Render3d]]
   [Assets Assets/Default [cbm fbx dae obj mtl glsl raw] [] [Render3d]]
   [Assets Assets/Default [wav ogg mp3] [] [Audio]]
   [Assets Assets/Default [nueffect nuscript csv] [] [Symbol]]
   [Assets Assets/Default [nuentity nugroup tsx tmx] [] []]]]
 [Gui
  [Assets Assets/Gui [bmp png psd ttf] [PsdToPng] [Render2d](/bryanedds/Nu/wiki/Assets-Assets/Gui-[bmp-png-psd-ttf]-[PsdToPng]-[Render2d)
   [Assets Assets/Gui [jpg jpeg tga tif tiff dds] [ConvertToDds] [Render3d]]
   [Assets Assets/Gui [cbm fbx dae obj mtl glsl raw] [] [Render3d]]
   [Assets Assets/Gui [wav ogg mp3] [] [Audio]]
   [Assets Assets/Gui [nueffect nuscript csv] [] [Symbol]]
   [Assets Assets/Gui [nuentity nugroup tsx tmx] [] []]]]
 [Gameplay
  [Assets Assets/Gameplay [bmp png psd ttf] [PsdToPng] [Render2d](/bryanedds/Nu/wiki/Assets-Assets/Gameplay-[bmp-png-psd-ttf]-[PsdToPng]-[Render2d)
   [Assets Assets/Gameplay [jpg jpeg tga tif tiff dds] [ConvertToDds] [Render3d]]
   [Assets Assets/Gameplay [cbm fbx dae obj mtl glsl raw] [] [Render3d]]
   [Assets Assets/Gameplay [wav ogg mp3] [] [Audio]]
   [Assets Assets/Gameplay [nueffect nuscript csv] [] [Symbol]]
   [Assets Assets/Gameplay [nuentity nugroup tsx tmx] [] []]]]]

This file uses Nu’s s-expression syntax. Why s-expression syntax? Because - https://vsynchronicity.com/2020/03/01/s-expression-the-ultimate-format/

You can edit the file directly, or you can edit it in the Asset Graph tab in Nu's editor, Gaia, like so -

image

Packages and Assets

An asset graph is composed of Packages that each hold multiple Asset descriptors. The packages in the above asset graph descriptor include Default, Gui, and Gameplay. In Nu, a single asset will never be loaded by itself. Instead, a package of assets containing a required asset is loaded (or unloaded) all at once. The Asset Graph allows you to declarative group together related assets in a package so they can be loaded as a unit.

In the above example that comes with the template project, the Default package contains all of the assets that comes with the engine and must exist for the engine to perform its basic presentation tasks. The Gui package contains all of the graphical user interface assets needed to present the content that exists outside of the main gameplay. The Gameplay package contains all of the assets that are needed to present the main gameplay itself.

Further, the use of the Asset Graph enables you to refer to assets by their asset and package name rather than their raw file name. Instead of setting a sprite image property to Assets/Default/Image.png, you instead set it to something like [Default Image] in the editor or use the Asset Picker or drag and drop from the Asset Viewer tab, like so -

image

You may notice that there is no need to manually specify which assets will be loaded in the editor or game before using them. This is because when an asset is used by the renderer or audio system, the renderer or audio system will automatically have load the asset's associated package on-demand. This is convenient and works great in Gaia, but this is not always what you want during gameplay. For example, if the use of an asset triggers a package load in the middle of an action sequence, the game could stall until the IO operations complete, thus resulting in an undesirable pause (tho an advanced technique known as asset stream is being planned, so even this may not be the case in the future). Whenever an on-demand package load happens, a note will be issued to the console that an asset package was loaded on-the-fly. Consider this a performance warning for your game. Fortunately, there is already a simple way to alleviate the potential issue of asset load stalls. When you know that the next section of your game will require a package of rendering assets, you can send a ‘load package’ message to the renderer like so –

    let world = World.loadRenderPackage2d "MyPackageName" world

Currently, this will cause the 2D renderer to immediately load all the all the assets in the package named MyPackageName which are associated with the 2d render system (which assets are associated with which system(s) is specified by the associations attribute of the Asset node in AssetGraph.nuag). The same can be done for the audio system as well.

Conversely, when you know that the assets in a loaded package won’t be used for a while, you can send an ‘unload package message’ to unload said packages assets via the corresponding World.unloadRenderPackage2d function.

Finally, there is a nifty feature in Gaia where the game’s currently assets can be rebuilt and reloaded at run-time (even during gameplay). This is done by pressing the Reload: Assets button found near the top-right of the window like so -

image

AssetGraph.nuag Syntax

WIP