メインコンテンツまでスキップ

Asset の読み込み

テクスチャ、マテリアル、3D モデルといった Asset は、どの 3D アプリにも欠かせません。一般に、読み込みに最も時間がかかります。PlayCanvas React では、さまざまな種類の Asset を読み込む専用フックと、Asset 読み込み用のユーティリティ関数を用意しています。すぐに使い始められつつ、いつ・どのように読み込むかを細かく制御できます。

基本的な使い方

Asset を読み込む最も簡単な方法は、専用フックのいずれかを使うことです。モデルGaussian splatテクスチャ環境マップフォントなど、それぞれにフックがあります。形はどれも似ており、PlayCanvas の Asset を返します。

GLB モデルには <Gltf> コンポーネントを使います。

import { useModel } from '@playcanvas/react/hooks';
import { Gltf } from '@playcanvas/react';

const { asset } = useModel('model.glb');
return <Gltf asset={asset} key={asset.id} />;

<Gltf> は GLB モデルを読み込んでレンダリングする推奨の方法です。モデル内部の構造にアクセスできるため、コンポーネントの変更、アニメーションの追加、物理の取り付けが容易です。変更が不要な単純なケースでは <Render asset={asset} /> も使えますが、<Gltf> の方が柔軟性があります。

アニメーションの追加、ライトの削除、物理コンポーネントの取り付けなど、GLB モデルの変更のページも参照してください。

プリロード

Asset フックは、読み込み情報やエラー状態も返します。読み込み中はプリローダーにフォールバックしたり、失敗時はエラーメッセージを表示したりできます。

model-viewer.tsx
import { useModel } from '@playcanvas/react/hooks';
import { Gltf } from '@playcanvas/react';

export function ModelViewer() {
const { asset, loading, error } = useModel('model.glb');

// If the asset is still loading, show a loading spinner
if (loading) return <LoadingSpinner />;

// If there is an error, show an error message
if (error) return <ErrorMessage message={error} />;

// If the asset is loaded, render it
return <Gltf asset={asset} key={asset.id} />;
}

Props を使った読み込み

一部の Asset は、読み込み方法をカスタマイズする追加プロパティを受け付けます。第 2 引数でフックに渡します。

// Load a texture with specific settings
const { asset } = useTexture('texture.jpg', {
mipmaps: true,
anisotropy: 16,
type: 'rgba'
});

Asset フック

Asset の種類ごとに異なるフックがあります。useAsset フックをラップして、より高度なフックを自作することもできます。

  • useModel — 3D GLTF/GLB モデルの読み込み
  • useTexture — テクスチャの読み込み
  • useSplat — Gaussian Splat の読み込み
  • useEnvAtlas — 環境アトラスの読み込み
  • useAsset — 任意のタイプの Asset の読み込み
  • useFont — フォントの読み込み

Asset のキャッシュ

同じファイルを何度も読み直さないよう、デフォルトで Asset はキャッシュされます。メモリの重複は抑えられますが、不要になったら正しくアンロードする必要があります。

unloading-model-viewer.tsx
import { useModel } from '@playcanvas/react/hooks';
import { useEffect } from 'react';

export function UnloadingModelViewer() {
const { asset, loading, error } = useModel('model.glb');

useEffect(() => {
return () => asset?.unload();
}, [asset]);

if (!asset) return null;

return <Gltf asset={asset} key={asset.id} />;
}
警告

Asset をアンロードするとグローバルから削除されます。 同じ Asset を使っている他のコンポーネントにも影響します。

カスタムの読み込み状態

Asset の読み込み状態を確認すれば、読み込み中はプレースホルダーやカスタムローダーを表示できます。細かく制御できます。

loading-spinner.tsx
import { useModel } from '@playcanvas/react/hooks';
import { Gltf } from '@playcanvas/react';

// A component that displays a model with a custom loading state
export function ModelWithCustomLoading() {
const { asset: plane, loading: planeLoading } = useModel('plane.glb');
const { asset: car, loading: carLoading } = useModel('car.glb');

if (planeLoading || carLoading) return <LoadingSpinner />;

return <>
<Gltf asset={car} key={car.id} />
<Gltf asset={plane} key={plane.id} />
</>
}

プログレッシブ読み込み

読み込みフックは、Asset を段階的に読み込む簡単な仕組みも提供します。まずはすぐにレンダリングし、あとから高品質なコンテンツを続けて読み込めます。

progressive-loading.tsx
import { Entity } from '@playcanvas/react';
import { GSplat } from '@playcanvas/react/components';
import { useSplat } from '@playcanvas/react/hooks';

// 段階的読み込みでスプラットを表示するコンポーネント
export function ProgressiveAsset() {
const { asset: low } = useSplat('./low-quality-model.sog'); // 低品質 Asset を読み込む
const { asset: high } = useSplat(low && './high-quality-model.sog'); // 低品質がロードされたら高品質 Asset を読み込む

if (!low && !high ) return null;

return <GSplat asset={high || low} />
}

データ取得ライブラリ

より高度なキャッシュや読み込み戦略が必要な場合は、React QuerySWR など、Promise ベースのライブラリと fetchAsset ユーティリティを組み合わせられます。

model-with-query.tsx
import { fetchAsset } from '@playcanvas/react/utils';
import { useQuery } from '@tanstack/react-query';

function useQueryModel(src: string) {
const query = useQuery({
queryKey: ['asset', src],
// 'container' is the type of asset we're loading (e.g., model, texture, etc.)
queryFn: () => fetchAsset({ app, url: src, type: 'container' })
});

return query;
}

export function ModelWithQuery() {
const { data: asset, isLoading } = useQueryModel('model.glb');

if (isLoading) return <LoadingSpinner />;
return <Gltf asset={asset} key={asset.id} />;
}

使い方の詳細は React Query のドキュメントSWR のドキュメントを参照してください。

Suspense との連携

React Query と SWR は Suspense 向けのサポートが組み込まれており、読み込み状態をより宣言的に扱えます。

import { fetchAsset } from '@playcanvas/react/utils';
import { Gltf } from '@playcanvas/react';
import { useQuery } from '@tanstack/react-query';

function useSuspendedQueryModel(src: string) {
const query = useQuery({
queryKey: ['asset', src],
queryFn: () => fetchAsset({ app, url: src, type: 'container' }),
suspense: true
});

return query;
}

export function ModelWithQuery() {
const { data: asset } = useSuspendedQueryModel('model.glb');
return <Gltf asset={asset} key={asset.id} />;
}

Suspense については React のドキュメント, および React Query のドキュメントSWR のドキュメントも参照してください。