アセットマネジメントシステム
A-Frame
にはアセットマネジメントシステムがあり、アセットを一カ所に集めたり、アセットを事前にキャッシュしてパフォーマンスを向上させることができます。アセット管理システムは、純粋にアセットをプリロードするためのものであることに注意してください。実行時にエンティティに設定するアセットについては、アセットへの直接のURL
を介して行うことができます。
ゲームやリッチな3D
体験では、シーンをレンダリングする前に、モデルやテクスチャなどのアセットをあらかじめロードしておくことが伝統的に行われています。これにより、アセットが視覚的に欠落しないようにし、レンダリング中にシーンがアセットを取得しようとしないようにするため、パフォーマンスが向上します。
アセットは<a-assets>
の中に置きます。<a-assets>
は<a-scene>
の中に置きます。
アセットには以下があります。
<a-asset-item>
- 3Dモデルや素材などの雑多なアセット<audio>
- サウンドファイル<img>
- 画像テクスチャ<video>
- ビデオテクスチャ
ブラウザがすべてのアセットを取得する(またはエラーになる)か、アセットシステムがタイムアウトになるまで、シーンはレンダリングまたは初期化されません。
# 例
<a-assets>
で資産を定義し、セレクタを使って実体からそれらの資産を指し示すことができます。
<a-scene>
<!-- Asset management system. -->
<a-assets>
<a-asset-item id="horse-obj" src="horse.obj"></a-asset-item>
<a-asset-item id="horse-mtl" src="horse.mtl"></a-asset-item>
<a-mixin id="giant" scale="5 5 5"></a-mixin>
<audio id="neigh" src="neigh.mp3"></audio>
<img id="advertisement" src="ad.png">
<video id="kentucky-derby" src="derby.mp4"></video>
</a-assets>
<!-- Scene. -->
<a-plane src="#advertisement"></a-plane>
<a-sound src="#neigh"></a-sound>
<a-entity geometry="primitive: plane" material="src: #kentucky-derby"></a-entity>
<a-entity mixin="giant" obj-model="obj: #horse-obj; mtl: #horse-mtl"></a-entity>
</a-scene>
シーンとそのエンティティは、初期化およびレンダリングの前に、すべてのアセットを(タイムアウトまで)待ちます。
# クロスオリジンリソース共有(CORS)
A-Frame
は XHRs (opens new window) を使ってアセットを取得するため、ブラウザのセキュリティ上、アセットが異なるドメインにある場合は、CORS(cross-origin resource sharing)ヘッダ (opens new window)を付けて提供する必要があります。もしくは、シーンと同じ場所でアセットをホストする必要があります。
その他のオプションについては、GitHub Pages
はすべてをCORS
ヘッダ付きで提供します。
シンプルなデプロイメント プラットフォームとして、GitHub Pages
をお勧めします。または、CORS
ヘッダーが設定されたファイルを提供する他のサービス(Amazon S3
など)。
その他のオプションでは、GitHub Pages (opens new window) はすべてを CORS
ヘッダで提供します。シンプルなデプロイメントプラットフォームとして、GitHub Pages
をお勧めします。または、CORS
ヘッダを設定してファイルを提供する他のサービス(Amazon S3
など)。
CORS
ヘッダが設定されている場合、<a-assets>
はリソースが異なるドメインにあることを検出すると、メディア要素(例:<audio>
、<img>
、<video>
)に自動的に crossorigin
属性を設定します。
# オーディオとビデオのプリロード
オーディオとビデオアセットがシーンをブロックするのは、autoplay
を設定した場合か、preload="auto"
を設定した場合のみです。
<a-scene>
<a-assets>
<!-- These will not block. -->
<audio src="blockus.mp3"></audio>
<video src="loadofblocks.mp4"></video>
<!-- These will block. -->
<audio src="blocky.mp3" autoplay></audio>
<video src="blockiscooking.mp4" preload="auto"></video>
</a-assets>
</a-scene>
# タイムアウトを設定する
タイムアウトを設定すると、すべてのアセットがロードされたかどうかに関係なく、シーンはレンダリングを開始し、エンティティは初期化を開始します。デフォルトのタイムアウトは3秒です。別のタイムアウトを設定するには、timeout
属性にミリ秒単位で数値を渡します。
一部のアセットの読み込みに時間がかかる場合、ネットワークが遅い場合にユーザーが一日中待つことがないように、適切なタイムアウトを設定することができます。
<a-scene>
<a-assets timeout="10000">
<!-- You got until the count of 10 to load else the show will go on without you. -->
<img src="bigimage.png">
</a-assets>
</a-scene>
# イベント
<a-assets>
と<a-asset-item>
はA-Frame
のノードなので、読み込みが終わるとloaded
イベントを発行します。
#
Event Name | 概要 |
---|---|
loaded | すべてのアセットがロードされた、またはアセットがタイムアウトした。 |
timeout | アセットがタイム・アウトした。 |
# 個別アセットの進捗を読み込む
# <a-asset-item>
<a-asset-item>
は three.js
のFileLoader
(opens new window) を呼び出します。
<a-asset-item>
はどのようなファイルタイプにも使用できます。終了したら、それはテキストレスポンスでそのデータメンバを設定します。
Event Name | 概要 |
---|---|
error | Fetchエラーです。イベントの詳細にはXMLHttpRequest のインスタンスを含むxhr |
progress | 進行時に発行される。イベントの詳細には、XMLHttpRequest インスタンスを含む xhr 、loadedBytes 、totalBytes が含まれます。 |
loaded | src で指定されたアセットがロードされました。 |
# <img>
画像は標準的なDOM要素なので、標準的なDOMイベントをリッスンすることができます。
Event Name | 概要 |
---|---|
load | イメージがロードされた |
# HTMLMediaElement
オーディオとビデオアセットはHTMLMediaElement
(opens new window)です。ブラウザはこれらの要素に対して特定のイベントを発生させます。ここでは便宜上、これらの要素について説明します。
Event Name | 概要 |
---|---|
error | アセットの読み込みにエラーが発生しました。 |
loadeddata | 進行中 |
progress | 進行中 |
A-Frame
は、この進捗イベントを利用して、ブラウザがバッファリングした時間とアセットの継続時間を比較し、アセットのロードを検知します。
# レスポンスタイプの指定
<a-asset-item>
で取得したコンテンツは、プレーンテキストとして返されます。arraybuffer
のような別のレスポンスタイプを使いたい場合は、<a-asset-item>
のresponse-type
属性を使用します。
<a-asset-item response-type="arraybuffer" src="model.gltf"></a-asset-item>
# 内部でどのように動いているか
A-Frame
の各要素は、AFRAME.ANode
のプロトタイプである<a-node>
を継承しています。
ANode
は読み込みと初期化の順番を制御します。ある要素(<a-assets>
、<a-asset-item>
、 <a-scene>
、<a-entity>
のいずれか)が初期化されるには、その子要素がすでに初期化されていなければなりません。ノードはボトムアップで初期化されます。
<a-assets>
は ANode
であり、ロードする前に子ノードがロードされるのを待ちます。また、<a-assets>
は <a-scene>
の子であるため、シーンは事実上すべてのアセットがロードされるのを待つ必要があります。また、<a-entity>
に追加のロード ロジックを追加し、<a-assets>
を定義した場合は、明示的に <a-assets>
のロードを待ちます。
<a-asset-item>
uses THREE.FileLoader
to fetch files. three.js stores the
returned data in THREE.Cache
. Every three.js loader inherits from
THREE.FileLoader
, whether they are a ColladaLoader
, OBJLoader
,
ImageLoader
, etc. And they all have access and are aware of the central
THREE.Cache
. If A-Frame already fetched a file, A-Frame won't try to fetch it
again.
<a-asset-item>
はTHREE.FileLoader
を使用してファイルを取得します。three.js
は返されたデータをTHREE.Cache
に格納します。ColladaLoader
、OBJLoader
、ImageLoader
など、すべてのthree.js
のローダーはTHREE.FileLoader
を継承しています。そして、それらはすべてTHREE.Cache
にアクセスし、中央のTHREE.Cache
を認識します。A-Frame
がすでにファイルを取得した場合、再取得は行いません。
このように、アセットでエンティティの初期化をブロックしているため、エンティティがロードされる頃には、すべてのアセットがすでにフェッチされていることになります。<a-asset-item>
を定義し、エンティティが THREE.FileLoader
を使用してファイルをフェッチしている限り、キャッシュは自動的に機能します。
# FileLoader
とキャッシュにアクセスする
もっと詳しく聞きたい場合はthree.js
のFileLoader
にアクセスすること。
console.log(document.querySelector('a-assets').fileLoader);
XHR
レスポンスを格納するキャッシュにアクセスするために。
console.log(THREE.Cache);