KhronosGroup / UnityGLTF

Runtime glTF 2.0 Loader for Unity3D
MIT License
1.79k stars 483 forks source link

Question: How can I share textures, meshes and other important assets b/w multiple instances of a GLB loaded from UnityGLTF #762

Open umeraamir-arthur opened 1 month ago

umeraamir-arthur commented 1 month ago

Hi @pfcDorn @hybridherbst

This one is rather a question. My use case now is to spawn multiple instances of same GLB in a scene. I'm using .Load() from GLTFComponent.cs in multiple game objects. It seems like they're having spikes every time I call .Load() because of the fact that all the assets including textures, meshes are loading multiple times instead of using same assets.

Is there a way to accomplish this situation where they can share important assets instead of creating new ones? Thankyou

hybridherbst commented 1 month ago

You can use Unity's Instantiate() calls as usual to duplicate a scene object. There is no caching of the loaded objects through GLTFComponent, because you could be modifying the object after loading, or the content of the file you're loading could have changed in the meantime.

umeraamir-arthur commented 1 month ago

I've tried this code and I think you're talking about same thing right? This one is insanely good. I can change materials colors and new Instanced Material will be created. Otherwise I don't need to change meshes and textures at runtime. PERFECT for my usecase..... Thanks MAN!!!!

image image

umeraamir-arthur commented 1 month ago

@hybridherbst one more question....

What if I want to enable GPU instancing for the materials? How can I achieve that?

hybridherbst commented 1 month ago

I think you can find all Renderers on the loaded object (before the first instantiate call), get all sharedMaterials, and enable material.enableInstancing.

GLTFSceneImporter does have an option to enable it as well but I'm not sure if that is exposed for runtime import (cc @pfcDorn)

umeraamir-arthur commented 1 month ago

Great @hybridherbst! And what about destroying these object.... Is it ??

Destroy() == Delete object
DestroyImmediate(object, true) == Delete object with resources (last one)

Can I replace DestroyImmediate() with something similar to Destroy() ?

hybridherbst commented 1 month ago

usually it's

if (Application.isPlaying)
   Destroy(target);
else
   DestroyImmediate(target);
umeraamir-arthur commented 1 month ago

I found this utility on LastLoadedScene. This MonoBehaviour is attached to the top most scene and is doing everything I needed without using custom Instantiate() calls and I can do Destroy() calls here. image

umeraamir-arthur commented 1 month ago

One thing I noticed that using this above method, there is a memory leak of animation clips as shown in the code below. I suppose that GLTFComponent.cs has reference of these AnimationClips that might be the reason. Even DestroyImmediate(object, true) was also not able to delete those clips and memory profilers shows them as leaked objects.

If I use Destroy(gameObject) which is the current game object with GLTFComponent.cs script then it was able to delete everything including those clips.

image image

hybridherbst commented 3 weeks ago

cc @pfcDorn can you look at the leak so that we can close this issue? You can also open a new issue for it (and close this one here)

pfcDorn commented 1 week ago

The Animation Clip issue will be fixed with 48355bb91649026dbd5c91f15908051edbb0d14a :) Thanks for testing!