跳到主要内容

加载与卸载

PlayCanvas 提供运行时动态加载和卸载资源的 API,可以精细控制内存占用,并按需加载内容。

加载资源​

加载已注册资源​

对于已经在资源注册表中的资源,例如编辑器添加的资源,使用 app.assets.load():

const asset = this.app.assets.find('My Texture');

asset.ready((asset) => {
// Asset is loaded and ready to use
const texture = asset.resource;
});

this.app.assets.load(asset);

从 URL 加载​

运行时从 URL 加载资源,使用 app.assets.loadFromUrl():

this.app.assets.loadFromUrl('path/to/texture.png', 'texture', (err, asset) => {
if (err) {
console.error('Failed to load texture:', err);
return;
}

// Asset is loaded and added to the registry
const texture = asset.resource;
});

第二个参数指定资源类型,常见类型包括:

  • texture:图像,如 PNG、JPG、WebP。
  • model:3D 模型,如 GLB。
  • audio:音频文件,如 MP3、OGG、WAV。
  • json:JSON 数据。
  • binary:二进制数据。
  • css:样式表。
  • html:HTML 文档。
  • script:JavaScript 文件。
  • shader:着色器代码。

携带选项加载​

从 URL 加载时可以传入额外选项:

this.app.assets.loadFromUrlAndFilename(
'path/to/model.glb',
'model.glb',
'container',
(err, asset) => {
if (err) {
console.error('Failed to load model:', err);
return;
}

// Create an entity from the loaded model
const entity = asset.resource.instantiateRenderEntity();
this.app.root.addChild(entity);
}
);

处理加载事件​

使用 ready()​

ready() 在资源加载完成时执行回调。如果资源已经加载,回调立即执行:

const asset = this.app.assets.find('My Model');

asset.ready((asset) => {
// Safe to use asset.resource here
});

// Trigger loading if not already loaded
if (!asset.loaded) {
this.app.assets.load(asset);
}

使用事件​

可以在单个资源或注册表上监听加载事件:

// Listen on a specific asset
asset.on('load', (asset) => {
console.log('Asset loaded:', asset.name);
});

asset.on('error', (err, asset) => {
console.error('Load failed:', asset.name, err);
});

// Listen on the registry for any asset
this.app.assets.on('load', (asset) => {
console.log('Some asset loaded:', asset.name);
});

配置重试​

资源加载失败时会自动重试,以应对 CDN 较慢、短暂断网等临时网络问题。默认情况下,每个失败请求最多重试 5 次,使用指数退避,间隔为 200、400、800、1600、3200 毫秒,上限为 5000 毫秒。

可以全局修改所有资源类型的重试设置:

// Override the default retry count
this.app.loader.enableRetry(3);

// Disable retries entirely - load failures are reported immediately
this.app.loader.disableRetry();

也可以按资源类型单独配置:

// Only retry texture loads more aggressively
this.app.loader.getHandler('texture').maxRetries = 10;

编辑器项目还可通过网络设置面板覆盖默认重试次数。

限制并发请求​

应用同时加载大量资源时,如果并发请求过多,浏览器可能以 net::ERR_INSUFFICIENT_RESOURCES 拒绝请求。为此,引擎限制并发资源请求数量,超出上限的请求进入队列,在较早请求完成后再发出。

默认上限为 128,既能兼容各浏览器,又能充分利用常见 CDN 吞吐量。可以全局修改:

// Allow at most 50 asset requests to be in flight at once
this.app.loader.maxConcurrentRequests = 50;

// Disable throttling entirely - every request is sent immediately
this.app.loader.maxConcurrentRequests = 0;
备注

此限制是进程级全局设置,应用于共享 HTTP 层,与浏览器的进程级资源限制相对应。同一页面存在多个应用时,以最后设置的值为准。它适用于所有基于 XMLHttpRequest 的加载,覆盖绝大多数资源。

编辑器项目也可通过网络设置面板配置。

携带凭据加载​

资源请求默认不携带凭据。如果资源位于需要 cookie、客户端 TLS 证书或 HTTP 身份验证的跨域主机上,可以全局启用凭据:

// Send all asset requests with credentials
this.app.loader.withCredentials = true;

必须在预加载或加载任何资源之前设置,使请求采用该配置。服务器必须返回非通配符的 Access-Control-Allow-Origin,以及 Access-Control-Allow-Credentials: true,否则浏览器会阻止响应。

备注

这也是进程级全局设置,作用于共享 HTTP 层。同一页面存在多个应用时,以最后设置的值为准。它适用于所有资源加载,包括直接获取数据而不经过 HTTP 层的高斯泼溅和资源包加载器。

卸载资源​

可以卸载不再需要的资源以释放内存:

const asset = this.app.assets.find('Large Texture');

// Unload the resource but keep the asset in the registry
asset.unload();

// The asset can be loaded again later
this.app.assets.load(asset);

移除资源​

要从注册表中彻底移除资源:

const asset = this.app.assets.find('Temporary Asset');

// Remove from registry (also unloads the resource)
this.app.assets.remove(asset);

加载多个资源​

要加载多个资源,并等待它们全部完成:

const assetNames = ['texture1', 'texture2', 'model1'];
const assets = assetNames.map(name => this.app.assets.find(name));

let loaded = 0;
const total = assets.length;

const onAssetLoad = () => {
loaded++;
if (loaded === total) {
// All assets loaded
this.onAllAssetsReady();
}
};

for (const asset of assets) {
asset.ready(onAssetLoad);
if (!asset.loaded) {
this.app.assets.load(asset);
}
}

最佳实践​

  • 卸载未使用的资源:切换关卡或场景时卸载资源,释放内存。
  • 使用 ready():它同时处理已经加载和尚未加载的情况。
  • 处理错误:动态加载始终应提供错误处理。
  • 成组加载:一起加载相关资源,避免视觉不一致。

另请参阅​