v2.4 Asset Manager Upgrade Guide
Author: Santy-Wang, Xunyi
This document will detail the considerations for upgrading an older project to v2.4.
Before v2.4, Acquire and load asset was implemented through the cc.loader module (including the APIs cc.loader.load, cc.loader.loadRes, cc.loader.loadResDir, etc.), which was primarily used to load resources. However, with the continuous development of Creator, developers' demands for resource management have been increasing. The original cc.loader module has been unable to meet a large number of resource management needs, and a new resource management module is in the air.
Therefore, Creator in v2.4 introduced a new resource management module -- Asset Manager. Compared to the previous cc.loader module, Asset Manager not only provides better loading performance, but also supports Asset Bundle, preload resources and more convenient resource release management. And Asset Manager also has strong extensibility, which greatly improves the development efficiency and user experience of developers. We recommend that all developers upgrade.
To bring a smooth upgrade experience, we will maintain compatibility with cc.loader related APIs, and most of the game project can run as usual, except for a few that use incompatible special usage APIs that must be manually upgraded. And we will only remove full compatibility with cc.loader when the time comes. If you are temporarily uncomfortable upgrading due to the project cycle, etc., you can keep the original writing while making sure the test passes.
Currently, when using those old APIs, the engine will output warnings and suggestions for upgradation. Please adjust the code according to the warnings and the instructions in this document and upgrade to the new usage. Unfortunately, due to an upgrade of the underlying layer, we have left behind a few incompatible APIs that will output error messages while running. If you have decided to make the upgrade, then please read the following carefully.
- For the Artist and Game Designer, all resources in your project (e.g. scenes, animations, prefab) do not need to be modified or upgraded.
- For Programmers, all APIs in the
cc.loadermodule that were used in the original code need to be changed to APIs fromcc.assetManager. The related content will be described in detail in this document.
Note: as v2.4 supports Asset Bundle, the subpackage feature in the project also needs to be upgraded, please refer to the Subpackage Upgrade Guide documentation for details.
Situations that require upgrading manually
- You use APIs that start with
cc.loaderin your own code, such ascc.loader.loaderRes,cc.loader.loadResDir,cc.loader.release, etc. - You use APIs that start with
cc.AssetLibraryin your own code, such ascc.AssetLibrary.loadAsset. - You use an API that starts with
cc.urlin your own code, such ascc.url.raw. - You use types such as
cc.Pipeline,cc.LoadingItemsin your own code. - You have used the
cc.macro.DOWNLOAD_MAX_CONCURRENTproperty in your own code.
Upgrade steps
- Back up your old projects
- Use Cocos Creator v2.4 in the Dashboard to open the project that needs to be upgraded, Creator will reimport the affected resources. The first import will take a little longer, and the main editor window will open after the import is complete. And more error or warning may appear on the Console panel, don't worry, open the code editor to update your code according to the error or warning message.
Replace the cc.loader related API with the cc.assetManager related API.
As of v2.4, cc.loader is no longer recommended and will be completely removed in subsequent releases, please replace it with the new resource management module cc.assetManager.
The relevant interface replacement about loading
If you use cc.loader.loadRes, cc.loader.loadResArray, cc.loader.loadResDir in your own code, use the corresponding API in cc.assetManager for the replacement. You can refer to the following replacements.
cc.loader.loadRes
The parameters of
cc.resources.loadare exactly equal tocc.loader.loadRes. Replace with the following:js// before cc.loader.loadRes(...); // after cc.resources.load(...);cc.loader.loadResArray
For reducing learning costs,
loadResArrayhas been merged withloadand the first parameter ofcc.resources.loadcan support multiple paths, so you can usecc.resources.loadto replace.js// before cc.loader.loadResArray(...); // after cc.resources.load(...);cc.loader.loadResDir
The parameters of
cc.resources.loadDirare equal to those ofcc.loader.loadResDir.js// before cc.loader.loadResDir(...); // after cc.resources.loadDir(...);Note: to simplify the interface, the load completion callback for
cc.resources.loadDirwill no longer provide a list of paths. Please avoid using the following:jscc.loader.loadResDir('images', cc.Texture2D, (err, assets, paths) => console.log(paths));If you want to query the paths list, you can use the following form:
jsvar infos = cc.resources.getDirWithPath('images', cc.Texture2D); let paths = infos.map(function (info) { return info.path; });cc.loader.load
If you use
cc.loader.loadto load remote images or audios in your own code, there is a special API for this in thecc.assetManagerfor ease of understanding, as follows:Loading remote images
js// before cc.loader.load('http://example.com/remote.jpg', (err, texture) => console.log(texture)); // after cc.assetManager.loadRemote('http://example.com/remote.jpg', (err, texture) => console.log(texture));Loading remote audio
js// before cc.loader.load('http://example.com/remote.mp3', (err, audioClip) => console.log(audioClip)); // after cc.assetManager.loadRemote('http://example.com/remote.mp3', (err, audioClip) => console.log(audioClip));Loading remote text
js// before cc.loader.load('http://example.com/equipment.txt', (err, text) => console.log(text)); // after cc.assetManager.loadRemote('http://example.com/equipment.txt', (err, textAsset) => console.log(textAsset.text));
Notes:
If you use
cc.loader.downloader.loadSubpackagein your own code to load a subpackage, please refer to the Subpackage Upgrade Guide to upgrade it.To avoid unnecessary errors,
cc.loader.onProgresshas no equivalent implementation incc.assetManager. You can implement your own global callback mechanism, but it is recommended that you pass callbacks to each load function to avoid interfering with each other during concurrent loading.
The relevant interface replacement about releasing
If you use cc.loader.release, cc.loader.releaseAsset, cc.loader.releaseRes, cc.loader.releaseResDir in your own code, please use the corresponding API in cc.assetManager for replacement. You can refer to the following replacements.
cc.loader.release
cc.loader.releasecan be replaced withcc.assetManager.releaseAsset.Note: in order to avoid user attention to some obscure properties of the resource,
cc.assetManager.releaseAssetno longer accepts arrays, resource UUIDs, resource URLs for release, only the resource itself can be accepted for release.js// before cc.loader.release(texture); // after cc.assetManager.releaseAsset(texture); // before cc.loader.release([texture1, texture2, texture3]); // after [texture1, texture2, texture3].forEach(t => cc.assetManager.releaseAsset(t)); // before var uuid = texture._uuid; cc.loader.release(uuid); // after cc.assetManager.releaseAsset(texture); // before var url = texture.url; cc.loader.release(url); // after cc.assetManager.releaseAsset(texture);Note: to increase ease of use, releasing resource dependencies in
cc.assetManagerwill no longer require manual access to resource dependencies, and an attempt will be made withincc.assetManager.releaseAssetto automatically release the associated dependencies, for example:js// before var assets = cc.loader.getDependsRecursively(texture); cc.loader.release(assets); // after cc.assetManager.releaseAsset(texture);cc.loader.releaseAsset
cc.loader.releaseAssetcan be replaced directly withcc.assetManager.releaseAsset.js// before cc.loader.releaseAsset(texture); // after cc.assetManager.releaseAsset(texture);cc.loader.releaseRes
cc.operator.releaseRescan be replaced directly withcc.resources.release.js// before cc.loader.releaseRes('images/a', cc.Texture2D); // after cc.resources.release('images/a', cc.Texture2D);cc.loader.releaseAll
cc.loader.releaseAllcan be replaced directly withcc.assetManager.releaseAll.js// before cc.loader.releaseAll(); // after cc.assetManager.releaseAll();
Notes:
For security reasons,
cc.loader.releaseResDirdoes not have a corresponding implementation incc.assetManager, please usecc.assetManager.releaseAssetorcc.resources.releasefor individual resource releases.Since the
cc.assetManager.releaseAssetautomatically releases dependent resources, you no longer need to explicitly callcc.loader.getDependsRecursively. If you need to find the dependency of the resource, please refer to the relevant API incc.assetManager.dependUtil.For security reasons,
cc.assetManageronly supports the Auto Release property set in the scene, andcc.loader.setAutoRelease,cc.loader.setAutoReleaseRecursively,cc.loader.isAutoReleaseAPIs have been removed. It is recommended that you use the new auto-release mechanism based on reference counting. Please refer to the Release Of Resources documentation for details.
Extension-related interface replacements
cc.Pipeline
If you have methods in your code that use
cc.loader.insertPipe,cc.loader.insertPipeAfter,cc.loader.appendPipe,cc.loader.addDownloadHandlers,cc.loader.addLoadHandlersseries APIs to extend the loading process ofcc.loader, or directly usecc.loader.assetLoader,cc.loader.md5Pipe,cc.loader.downloader,cc.loader.loader,cc.loader.subPackPipe, here are the detailed alternatives.Because
cc.assetManageris a more general module and no longer inherits fromcc.Pipeline,cc.assetManagerno longer implementscc.handler.insertPipe,cc.handler.insertPipeAfter,cc.handler.appendPipe. Please replace with the following code:js// before var pipe1 = { id: 'pipe1', handle: (item, done) => { let result = doSomething(item.uuid); done(null, result); } }; var pipe2 = { id: 'pipe2', handle: (item, done) => { let result = doSomething(item.content); done(null, result); } }; cc.loader.insertPipe(pipe1, 1); cc.loader.appendPipe(pipe2); // after function pipe1 (task, done) { let output = []; for (var i = 0; i < task.input.length; i++) { let item = task.input[i]; item.content = doSomething(item.uuid); output.push(item); } task.output = output; done(null); } function pipe2 (task, done) { let output = []; for (var i = 0; i < task.input.length; i++) { let item = task.input[i]; item.content = doSomething(item.content); output.push(item); } task.output = output; done(null); } cc.assetManager.pipeline.insert(pipe1, 1); cc.assetManager.pipeline.append(pipe2);Notes:
cc.assetManagerno longer inherits byPipeline, but by multiplePipelineinstances owned undercc.assetManager. Please refer to the Pipeline and Task documentation for details.For ease of use, the definition of Pipe no longer requires the definition of an object with a
handlemethod and anid, just a single method. See Pipeline and Task documentation for details.In order to simplify the logic and improve performance, what is processed in Pipe is no longer a
itembut ataskobject, see Pipeline and Task documentation for details.In order to reduce learning costs, APIs in the form of
insertPipeAfterare no longer supported inPipeline, so please useinsertto insert the specified location.
addDownloadHandlers, addLoadHandlers
For modularity reasons,
addDownloadHandlersandaddLoadHandlersare not implemented incc.assetManager, please refer to the following for replacement:js// before var customHandler = (item, cb) => { let result = doSomething(item.url); cb(null, result); }; cc.loader.addDownloadHandlers({png: customHandler}); // after var customHandler = (url, options, cb) => { let result = doSomething(url); cb(null, result); }; cc.assetManager.downloader.register('.png', customHandler);Or:
js// before var customHandler = (item, cb) => { let result = doSomething(item.content); cb(null, result); }; cc.loader.addLoadHandlers({png: customHandler}); // after var customHandler = (file, options, cb) => { let result = doSomething(file); cb(null, result); }; cc.assetManager.parser.register('.png', customHandler);Notes:
Since both the download module and the parsing module rely on extensions to match the corresponding processing method. So when calling
register, the incoming first parameter needs to start with..For the sake of modularity, the custom processing method will no longer pass in an
itemobject, but will pass in its associated information directly. The custom processing method ofdownloaderpasses in the URL to be downloaded, andparserpasses in the file to be parsed. For more information aboutdownloaderandparser, please refer to the Download and Parse documentation.The new expansion mechanism provides an additional
optionsparameter that can greatly increase flexibility. However, if you don't need to configure the engine's built-in or custom parameters, you can ignore it. Please refer to the Optional parameter documentation for details.
downloader, loader, md5Pipe, subPackPipe
cc.loader.downloadercan be replaced bycc.assetManager.downloader, andcc.loader.loadercan be replaced bycc.assetManager.parser. For details, see Download and Parse documentation or the corresponding API documentation cc.assetManager.downloader and cc.assetManager.parser.Note: for performance, modularity and readability reasons,
cc.loader.assetLoader,cc.loader.md5Pipe,cc.loader.subPackPipehave been merged intocc.assetManager.transformPipelineand you should avoid using any of the methods and properties in these three modules. Details aboutcc.assetManager.transformPipelinecan be found in Pipeline and Tasks documentation.
Other changes
The cc.url and cc.AssetLibrary have been removed in v2.4, so avoid using any methods and properties of cc.url and cc.AssetLibrary.
Pipeline can be replaced by cc.AssetManager.Pipeline:
// before
var pipe1 = {
id: 'pipe1',
handle: function (item, cb) {
let result = doSomething(item);
cb(null, result);
}
}
var pipeline = new cc.Pipeline([pipe1]);
// after
function pipe1 (task, cb) {
task.output = doSomething(task.input);
cb(null);
}
var pipeline = new cc.AssetManager.Pipeline('test', [pipe1]);Note:
cc.LoadingItemis no longer supported incc.assetManager, please avoid using this type.
To support more loading strategies, cc.macro.DOWNLOAD_MAX_CONCURRENT has been removed from cc.macro and you can replace it with the following:
// before
cc.macro.DOWNLOAD_MAX_CONCURRENT = 10;
// after
cc.assetManager.downloader.maxConcurrency = 10;Or:
// before
cc.macro.DOWNLOAD_MAX_CONCURRENT = 10;
// after (set a preset value)
cc.assetManager.presets['default'].maxConcurrency = 10;Please refer to the Download and Parse documentation for details.