Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.0] FirstPerson.SetupAsync 修正 #1252

Merged
merged 2 commits into from Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 13 additions & 13 deletions Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs
Expand Up @@ -110,25 +110,25 @@ public static RuntimeGltfInstance AttachTo(GameObject go, ImporterContext contex

foreach (var renderer in go.GetComponentsInChildren<Renderer>())
{
loaded._renderers.Add(renderer);

switch (renderer)
{
case MeshRenderer meshRenderer:
loaded._meshRenderers.Add(meshRenderer);
break;
case SkinnedMeshRenderer skinnedMeshRenderer:
loaded._skinnedMeshRenderers.Add(skinnedMeshRenderer);
break;
}
loaded.AddRenderer(renderer);
}

return loaded;
}

public void AddRenderers(IEnumerable<Renderer> renderers)
public void AddRenderer(Renderer renderer)
{
_renderers.AddRange(renderers);
_renderers.Add(renderer);

switch (renderer)
{
case MeshRenderer meshRenderer:
_meshRenderers.Add(meshRenderer);
break;
case SkinnedMeshRenderer skinnedMeshRenderer:
_skinnedMeshRenderers.Add(skinnedMeshRenderer);
break;
}
}

public void ShowMeshes()
Expand Down
Expand Up @@ -49,20 +49,22 @@ private async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMe

var go = new GameObject("_headless_" + renderer.name);
var erased = go.AddComponent<SkinnedMeshRenderer>();
erased.enabled = false; // hide
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

生成するときに Renderer は disable。

erased.sharedMesh = mesh;
erased.sharedMaterials = renderer.sharedMaterials;
erased.bones = renderer.bones;
erased.rootBone = renderer.rootBone;
erased.updateWhenOffscreen = true;

return erased;
}

bool m_done;

async Task<SkinnedMeshRenderer> SetupRendererAsync(GameObject go, Transform FirstPersonBone, RendererFirstPersonFlags x,
async Task SetupRendererAsync(GameObject go, Transform FirstPersonBone, RendererFirstPersonFlags x,
(int FirstPersonOnly, int ThirdPersonOnly) layer, IAwaitCaller awaitCaller = null)
{
var runtime = go.GetComponent<UniGLTF.RuntimeGltfInstance>();

switch (x.FirstPersonFlag)
{
case UniGLTF.Extensions.VRMC_vrm.FirstPersonType.auto:
Expand All @@ -77,10 +79,12 @@ private async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMe

// 頭を取り除いた複製モデルを作成し、1人称用にする
var headless = await CreateHeadlessMeshAsync(smr, eraseBones, awaitCaller);
headless.enabled = false;
headless.gameObject.layer = layer.FirstPersonOnly;
headless.transform.SetParent(smr.transform, false);
return headless;
if (runtime != null)
{
runtime.AddRenderer(headless);
}
}
else
{
Expand Down Expand Up @@ -120,8 +124,6 @@ private async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMe
// 特に何もしない。すべてのカメラで描画される
break;
}

return null;
}

/// <summary>
Expand All @@ -137,7 +139,7 @@ private async static Task<SkinnedMeshRenderer> CreateHeadlessMeshAsync(SkinnedMe
/// <param name="thirdPersonOnlyLayer"></param>
/// <param name="awaitCaller"></param>
/// <returns></returns>
public async Task<List<SkinnedMeshRenderer>> SetupAsync(GameObject go, int? firstPersonOnlyLayer = default, int? thirdPersonOnlyLayer = default, IAwaitCaller awaitCaller = default)
public async Task SetupAsync(GameObject go, int? firstPersonOnlyLayer = default, int? thirdPersonOnlyLayer = default, IAwaitCaller awaitCaller = default)
{
if (awaitCaller == null)
{
Expand All @@ -148,23 +150,17 @@ public async Task<List<SkinnedMeshRenderer>> SetupAsync(GameObject go, int? firs
Vrm10FirstPersonLayerSettings.GetFirstPersonOnlyLayer(firstPersonOnlyLayer),
Vrm10FirstPersonLayerSettings.GetThirdPersonOnlyLayer(thirdPersonOnlyLayer));

var created = new List<SkinnedMeshRenderer>();
if (m_done)
{
return created;
return;
}
m_done = true;

var FirstPersonBone = go.GetComponent<Animator>().GetBoneTransform(HumanBodyBones.Head);
foreach (var x in Renderers)
{
var renderer = await SetupRendererAsync(go, FirstPersonBone, x, layer, awaitCaller);
if (renderer)
{
created.Add(renderer);
}
await SetupRendererAsync(go, FirstPersonBone, x, layer, awaitCaller);
}
return created;
}
}
}
Expand Up @@ -99,8 +99,7 @@ async Task<RuntimeGltfInstance> LoadAsync(string path)

// VR用 FirstPerson 設定
var controller = instance.GetComponent<Vrm10Instance>();
var created = await controller.Vrm.FirstPerson.SetupAsync(controller.gameObject);
instance.AddRenderers(created);
await controller.Vrm.FirstPerson.SetupAsync(controller.gameObject);

return instance;
}
Expand Down
Expand Up @@ -10,7 +10,10 @@ namespace VRMShaders
/// この interface を実装するクラスは、利用後に破棄すべき UnityObject を保持する可能性があるので
/// Dispose により解放すること。
///
/// TransferOwnership により、破棄責任を移譲することができる。
/// [Runtime] TransferOwnership により、破棄責任を RuntimeGltfInstance に移譲する。
/// RuntimeGltfInstance.OnDestroy でこれを破棄する。
/// [Editor] TransferOwnership により、Asset化して破棄しない
/// DestroyするとAssetが消えてしまう。
///
/// </summary>
public interface IResponsibilityForDestroyObjects : IDisposable
Expand Down
53 changes: 53 additions & 0 deletions docs/implementation/runtime_resource_management.md
@@ -0,0 +1,53 @@
# Runtime のリソース管理について

Runtime Import で `Texture`, `Material`, `Mesh` などのリソースを Root の `GameObject.OnDestroy`
と同時に `UnityEngine.Object.Destroy` したい。

## RuntimeGltfInstance

`RuntimeGltfInstance.OnDestroy` で破棄を実行するようにした。

```
ImporterContext
[Own]List<Mesh>
AnimationClipFactory[Own]List<Animation>
TextureFactory[Own]List<Texture>
MaterialFactory[Own]List<Material>

👇 ImporterContext.LoadAsync
RuntimeGltfInstance.AttachTo
ImporterContext.TransferOwnership

RuntimeGltfInstance
[Own]List<Mesh>
[Own]List<Animation>
[Own]List<Texture>
[Own]List<Material>
```

> VRM-0.X では `RuntimeGltfInstance` にリソースを委譲している。

## Vrm10Instance

```
Vrm10Importer
[Own]HumanoidAvatar
[Own]Vrm10Object
[Own]List<Vrm10Expression>

👇 Vrm10Importer.LoadAsync

RuntimeGltfInstance
[Own]HumanoidAvatar
[Own]VrmObject
[Own]List<VrmExpression>
```

### FirstPerson

```
👇 Vrm10Instance.FirstPerson.SetupAsync

RuntimeGltfInstance
[Own]List<Mesh>.Add(headless)
```
7 changes: 7 additions & 0 deletions docs/index.md
Expand Up @@ -37,6 +37,13 @@ vrm0/0_58_blendshape.md
vrm0/firstperson.md
```

## 実装メモ

```{toctree}

implementation/runtime_resource_management.md
```

### Samples

- SimpleViewer
Expand Down
12 changes: 4 additions & 8 deletions docs/vrm1/vrm1_firstperson.md
Expand Up @@ -7,8 +7,7 @@ VR向け FirstPerson 設定の初期化手順です。
1. Load する
2. Vrm10Instance を取得する
3. `controller.Vrm.FirstPerson.SetupAsync` を呼び出す
4. `controller.Vrm.FirstPerson.SetupAsync` した結果新規に作成されたモデルを `RuntimeGltfInstance` に渡す
5. ShowMeshes
4. ShowMeshes

```csharp
async Task<RuntimeGltfInstance> LoadAsync(string path)
Expand All @@ -26,13 +25,10 @@ async Task<RuntimeGltfInstance> LoadAsync(string path)
// 2.
var controller = instance.GetComponent<Vrm10Instance>();

// 3.
var created = await controller.Vrm.FirstPerson.SetupAsync(controller.gameObject);
// 3. The headless model that created is added to instance
await controller.Vrm.FirstPerson.SetupAsync(controller.gameObject);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最小限でよさそう。


// 4.
instance.AddRenderers(created);

// 5.
// 4.
instance.ShowMeshes();

return instance;
Expand Down