mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-19 13:37:26 -05:00
164 lines
7.9 KiB
Markdown
164 lines
7.9 KiB
Markdown
# `v0.68` RuntimeImport DisposeOnGameObjectDestroyed(obsolete)
|
|
|
|
## 過去バージョンからの仕様変更
|
|
|
|
`ImporterContext` の仕様を変更しました。
|
|
|
|
* ロード処理が Parse と Load の 2 ステップに分かれました。
|
|
* Parse 処理をメインスレッド以外で処理することができます。
|
|
* 非同期ロード関数 `ImporterContext.LoadAsync` の実装を `Task` に変更しました。
|
|
* これまで明示的に破棄できなかった `UnityEngine.Object` リソースを破棄できるようになりました。
|
|
* リソースのリークを防ぐことができます。
|
|
* `ImporterContext.Dispose` を呼び出すべきタイミングを「ロード処理終了時」に変更しました。
|
|
* 呼び出して破棄する前に、後述の `ImporterContext.DisposeOnGameObjectDestroyed` を呼び出してください。
|
|
* 以前の仕様は「生成したモデルの破棄時」に呼び出すべき関数でした。
|
|
* `ImporterContext.DisposeOnGameObjectDestroyed` 関数を追加しました。
|
|
* VRM モデルが必要とするリソース (Texture, Material, Mesh, etc) を破棄する責務を GameObject に移譲できます。
|
|
* VRM の GameObject の破棄タイミングでリソース (Texture, Material, Mesh, etc) を破棄します。
|
|
|
|
|
|
## サンプルコード(同期的ロード)
|
|
|
|
```csharp
|
|
using UniGLTF;
|
|
using UnityEngine;
|
|
using VRM;
|
|
|
|
namespace YourNameSpace
|
|
{
|
|
public sealed class LoadVrmSample : MonoBehaviour
|
|
{
|
|
[SerializeField] private string _vrmFilePath;
|
|
private GameObject _vrmGameObject;
|
|
|
|
private void Start()
|
|
{
|
|
_vrmGameObject = LoadVrm(_vrmFilePath);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
DestroyVrm(_vrmGameObject);
|
|
}
|
|
|
|
private GameObject LoadVrm(string vrmFilePath)
|
|
{
|
|
// 1. GltfParser を呼び出します。
|
|
// GltfParser はファイルから JSON 情報とバイナリデータを読み出します。
|
|
var parser = new GltfParser();
|
|
parser.ParsePath(vrmFilePath);
|
|
|
|
// 2. GltfParser のインスタンスを引数にして VRMImporterContext を作成します。
|
|
// VRMImporterContext は VRM のロードを実際に行うクラスです。
|
|
using (var context = new VRMImporterContext(parser))
|
|
{
|
|
// 3. Load 関数を呼び出し、VRM の GameObject を生成します。
|
|
context.Load();
|
|
|
|
// 4. (任意) SkinnedMeshRenderer の UpdateWhenOffscreen を有効にできる便利関数です。
|
|
// https://docs.unity3d.com/2019.4/Documentation/ScriptReference/SkinnedMeshRenderer-updateWhenOffscreen.html
|
|
context.EnableUpdateWhenOffscreen();
|
|
|
|
// 5. VRM モデルを表示します。
|
|
context.ShowMeshes();
|
|
|
|
// 6. VRM の GameObject が実際に使用している UnityEngine.Object リソースの寿命を VRM の GameObject に紐付けます。
|
|
// つまり VRM の GameObject の破棄時に、実際に使用しているリソース (Texture, Material, Mesh, etc) をまとめて破棄することができます。
|
|
context.DisposeOnGameObjectDestroyed();
|
|
|
|
// 7. Root の GameObject を return します。
|
|
// Root の GameObject とは VRMMeta コンポーネントが付与されている GameObject のことです。
|
|
return context.Root;
|
|
}
|
|
// 8. using スコープを抜けて context が破棄されると、 VRMImporterContext が保持する UnityEngine.Object リソースが破棄されます。
|
|
// このとき破棄されるリソースは、 glTF ファイルには含まれているが VRM の GameObject には割り当てられていないテクスチャなどです。
|
|
// 手順 6. で VRM の GameObject に紐付けたリソースは、ここでは破棄されません。
|
|
}
|
|
|
|
private void DestroyVrm(GameObject vrmGameObject)
|
|
{
|
|
// 9. 生成された VRM の GameObject を破棄します。
|
|
// GameObject を破棄すれば、紐づくリソース (Texture, Material, Mesh, etc) も破棄されます。
|
|
UnityEngine.Object.Destroy(vrmGameObject);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## サンプルコード(非同期ロード)
|
|
|
|
```csharp
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
using UniGLTF;
|
|
using UnityEngine;
|
|
using VRM;
|
|
|
|
namespace YourNameSpace
|
|
{
|
|
public sealed class LoadVrmAsyncSample : MonoBehaviour
|
|
{
|
|
[SerializeField] private string _vrmFilePath;
|
|
private GameObject _vrmGameObject;
|
|
|
|
private async void Start()
|
|
{
|
|
// 簡便のため、このサンプルではキャンセル処理などは考慮しません。
|
|
_vrmGameObject = await LoadVrmAsync(_vrmFilePath);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
DestroyVrm(_vrmGameObject);
|
|
}
|
|
|
|
private async Task<GameObject> LoadVrmAsync(string vrmFilePath)
|
|
{
|
|
// 1. GltfParser を呼び出します。
|
|
// GltfParser はファイルから JSON 情報とバイナリデータを読み出します。
|
|
// GltfParser は Unity のメインスレッド以外で実行できます。
|
|
var parser = new GltfParser();
|
|
await Task.Run(() =>
|
|
{
|
|
var file = File.ReadAllBytes(vrmFilePath);
|
|
parser.ParseGlb(file);
|
|
});
|
|
|
|
// 2. GltfParser のインスタンスを引数にして VRMImporterContext を作成します。
|
|
// VRMImporterContext は VRM のロードを実際に行うクラスです。
|
|
using (var context = new VRMImporterContext(parser))
|
|
{
|
|
// 3. Load 関数を呼び出し、VRM の GameObject を生成します。
|
|
// Load 処理は数フレームの時間を要します。
|
|
await context.LoadAsync();
|
|
|
|
// 4. (任意) SkinnedMeshRenderer の UpdateWhenOffscreen を有効にできる便利関数です。
|
|
// https://docs.unity3d.com/2019.4/Documentation/ScriptReference/SkinnedMeshRenderer-updateWhenOffscreen.html
|
|
context.EnableUpdateWhenOffscreen();
|
|
|
|
// 5. VRM モデルを表示します。
|
|
context.ShowMeshes();
|
|
|
|
// 6. VRM の GameObject が実際に使用している UnityEngine.Object リソースの寿命を VRM の GameObject に紐付けます。
|
|
// つまり VRM の GameObject の破棄時に、実際に使用しているリソース (Texture, Material, Mesh, etc) をまとめて破棄することができます。
|
|
context.DisposeOnGameObjectDestroyed();
|
|
|
|
// 7. Root の GameObject を return します。
|
|
// Root の GameObject とは VRMMeta コンポーネントが付与されている GameObject のことです。
|
|
return context.Root;
|
|
}
|
|
// 8. using スコープを抜けて context が破棄されると、 VRMImporterContext が保持する UnityEngine.Object リソースが破棄されます。
|
|
// このとき破棄されるリソースは、 glTF ファイルには含まれているが VRM の GameObject には割り当てられていないテクスチャなどです。
|
|
// 手順 6. で VRM の GameObject に紐付けたリソースは、ここでは破棄されません。
|
|
}
|
|
|
|
private void DestroyVrm(GameObject vrmGameObject)
|
|
{
|
|
// 9. 生成された VRM の GameObject を破棄します。
|
|
// GameObject を破棄すれば、紐づくリソース (Texture, Material, Mesh, etc) も破棄されます。
|
|
UnityEngine.Object.Destroy(vrmGameObject);
|
|
}
|
|
}
|
|
}
|
|
```
|