-
-
Notifications
You must be signed in to change notification settings - Fork 78
AssetManifest
A graphical application usually depends on tons of assets (textures, models, etc) to process and render. It is usually not possible to deploy all assets to client machine at installation time, instead, assets are downloaded from the server usually on first use.
NPL/ParaEngine has built-in support for asynchronous asset loading via asset manifest system. Basically, it resolves two problems:
- Use a plain text file to look up and download assets in the background in several worker threads.
- Most UI and 3d objects in ParaEngine provide a synchronous interface to set assets as if they are already available. In reality, they will automatically resolve assets (also their dependencies) when those assets are available locally.
When an application starts, NPLRuntime will read all Assets_manifest*.txt
file under the root directory. Each file has the following content
format is [relative path],md5,fileSize
if the name ends with .z, it is zipped. This could be 4MB uncompressed in size md5 is checksum code of the file. fileSize is the compressed file size.
audio/music.mp3.z,3799134715,22032
model/building/tree.dds.z,2957514200,949
model/building/tree.x.z,2551621901,816
games/tutorial.swf,1157008036,171105
When one of the async loader try to load an application asset(texture, model, etc), it will first search in AssetManifest using the TO-LOWER-CASED asset path, such as (model/building/tree.x). it will then search the "temp/cache/" directory for a matching file
The file matching is done by comparing the line in the asset file with the filename in the cache directory, using their md5 and size. For example:
audio/music.mp3.z,3799134715,22032 matches to file 379913471522032
Example Usage:
AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile("Texture/somefile.dds");
if(pEntry && pEntry->DoesFileExist())
{
// Load from file pEntry->GetLocalFileName();
}
You can also load additional asset manifest file(s) at runtime.
local asset_manager = ParaEngine.GetAttributeObject():GetChild("AssetManager");
local asset_manifest = asset_manager:GetChild("CAssetManifest");
asset_manifest:SetField("LoadManifestFile", "path_to_your_asset_manifest.txt");
At runtime, we can dynamically set the asset web server, where the game engine will be used to download these asset files, such as below.
ParaAsset.SetAssetServerUrl("http://cdn.keepwork.com/update61/assetdownload/update/");
In a real application, like in paracraft, this is configured in GameClient.config.xml
file.
<asset_server_addresses bg_loader_list ="http://update.61.com/haqi/assetupdate">
<address host="http://update.61.com/haqi/assetupdate/"/>
</asset_server_addresses>
And we usually build toolchain to generate those asset files and upload them to a CDN web asset server.
For example, to deploy a file like character/cc/02human/paperman/boy02.x
we will generate a file at CDN server character/cc/02human/paperman/boy02.x.z,cb219320ace5067872f528e2f2a3427a,2518758
And if our asset server is http://cdn.keepwork.com/update61/assetdownload/update/
then, the game engine will download the following file at runtime. The game engine will also check its md5.
http://cdn.keepwork.com/update61/assetdownload/update/character/cc/02human/paperman/boy02.x.z,cb219320ace5067872f528e2f2a3427a,2518758
So you need to append character/cc/02human/paperman/boy02.x.z,cb219320ace5067872f528e2f2a3427a,2518758
to a separate line in assets_manifest.txt
or assets_manifest[XXX].txt
Sometimes, you may want to preload assets like textures and models and display a progress bar before presenting to the user. This can be done using the ParaAssetObject's LoadAsset, IsLoaded, UnloadAsset, Reload
method.
Because asset is async loaded, calling LoadAsset() does not mean the asset is loaded, it may take a few seconds before IsLoaded
can return true. So one should check it periodically in a timer.
local asset = ParaAsset.LoadTexture("", "texture/white.png", 1);
-- local asset = ParaAsset.LoadStaticMesh("", model_filename);
asset:LoadAsset();
local mytimer = commonlib.Timer:new({callbackFunc = function(timer)
if(asset:IsLoaded()) then
echo("asset loaded!");
timer:Change();
end
end})
mytimer:Change(0, 1000);
There is a helper class for this task in script/ide/AssetPreloader.lua
Download Paracraft | ParacraftSDK | copyright by tatfook 2016 | upload image