using System.Collections.Generic; using System.Linq; using UnityEngine; using VRMShaders; namespace UniGLTF { /// /// ImporterContext の Load 結果の GltfModel /// /// Runtime でモデルを Destory したときに関連リソース(Texture, Material...などの UnityEngine.Object)を自動的に Destroy する。 /// public class RuntimeGltfInstance : MonoBehaviour, IResponsibilityForDestroyObjects { /// /// this is UniGLTF root gameObject /// public GameObject Root => (this != null) ? this.gameObject : null; /// /// Transforms with gltf node index. /// public IReadOnlyList Nodes => _nodes; /// /// Runtime resources. /// ex. Material, Texture, AnimationClip, Mesh. /// public IReadOnlyList<(SubAssetKey, UnityEngine.Object)> RuntimeResources => _resources; /// /// Materials. /// public IReadOnlyList Materials => _materials; /// /// Textures. /// public IReadOnlyList Textures => _textures; /// /// Animation Clips. /// public IReadOnlyList AnimationClips => _animationClips; /// /// Meshes. /// public IReadOnlyList Meshes => _meshes; /// /// Renderers. /// ex. MeshRenderer, SkinnedMeshRenderer. /// public IReadOnlyList Renderers => _renderers; /// /// Mesh Renderers. /// public IReadOnlyList MeshRenderers => _meshRenderers; /// /// Skinned Mesh Renderers. /// public IReadOnlyList SkinnedMeshRenderers => _skinnedMeshRenderers; /// /// ShowMeshes の対象になる Renderer。 /// Destroy対象とは無関係なので、自由に操作して OK。 /// /// /// public IList VisibleRenderers => _visibleRenderers; private readonly List _nodes = new List(); private readonly List<(SubAssetKey, UnityEngine.Object)> _resources = new List<(SubAssetKey, UnityEngine.Object)>(); private readonly List _materials = new List(); private readonly List _textures = new List(); private readonly List _animationClips = new List(); private readonly List _meshes = new List(); private readonly List _renderers = new List(); private readonly List _meshRenderers = new List(); private readonly List _skinnedMeshRenderers = new List(); private readonly List _visibleRenderers = new List(); public static RuntimeGltfInstance AttachTo(GameObject go, ImporterContext context) { var loaded = go.AddComponent(); foreach (var node in context.Nodes) { // Maintain index order. loaded._nodes.Add(node); } context.TransferOwnership((k, o) => { if (o == null) return; loaded._resources.Add((k, o)); switch (o) { case Material material: loaded._materials.Add(material); break; case Texture texture: loaded._textures.Add(texture); break; case AnimationClip animationClip: loaded._animationClips.Add(animationClip); break; case Mesh mesh: loaded._meshes.Add(mesh); break; } }); foreach (var renderer in go.GetComponentsInChildren()) { loaded.AddRenderer(renderer); } return loaded; } public void AddRenderer(Renderer renderer) { _renderers.Add(renderer); VisibleRenderers.Add(renderer); switch (renderer) { case MeshRenderer meshRenderer: _meshRenderers.Add(meshRenderer); break; case SkinnedMeshRenderer skinnedMeshRenderer: _skinnedMeshRenderers.Add(skinnedMeshRenderer); break; } } public void ShowMeshes() { foreach (var r in VisibleRenderers) { r.enabled = true; } } public void EnableUpdateWhenOffscreen() { foreach (var skinnedMeshRenderer in SkinnedMeshRenderers) { skinnedMeshRenderer.updateWhenOffscreen = true; } } void OnDestroy() { Debug.Log("UnityResourceDestroyer.OnDestroy"); foreach (var (_, obj) in _resources) { UnityObjectDestoyer.DestroyRuntimeOrEditor(obj); } } public void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take) { foreach (var (key, x) in _resources.ToArray()) { take(key, x); _resources.Remove((key, x)); } } public void Dispose() { if (this != null && this.gameObject != null) { UnityObjectDestoyer.DestroyRuntimeOrEditor(this.gameObject); } } } }