I’m generating a cache of edges for meshes and storing it in a ScriptableObject. Most of the meshes in the project are processed at editor time, and then a little data about each one is stored in the edge cache. Then at runtime, when a mesh is loaded, it looks up the mesh in the ScriptableObject cache. This lets me disable read/write on every single mesh import and still have some of the data around as well as skip the processing step on load.
So far so good, and all this is working! However, right now, the ScriptableObject holds direct references to the meshes:
public class EdgeCache : ScriptableObject
{
internal Entry[] entries;
[Serializable]
internal struct Entry
{
[SerializeField] public Mesh mesh;
[SerializeField] public bool isManifold;
[SerializeField] public int[] _data;
}
}
The whole edge cache itself is only a couple megabytes max, so I don’t mind just loading it once on startup and keeping it in memory for the application lifetime. However, when I load the ScriptableObject, every single mesh will also be loaded, correct? That’s not what I want at all. I want a “weak reference” to those meshes (eg a GUID) so if that mesh appears in a scene and is already loaded, I can get the edge data, but the underlying mesh can be unloaded or not exist.
In the editor, I can use GlobalObjectId , which looks perfect, but that’s only available in the editor and not at runtime. InstanceIDs are not persistent. I can try to do something silly with names, but those are guaranteed to be unique and things can be renamed. Is there any robust way to do this at runtime?
We use AssetRef struct similar to AddresableReference that store GUID of asset as string
At run time we just load it through asset bundle system having catalog that know in wich bundle specified GUID is stored
All assets with references compile into bundle with additional names as their editor GUIDs so we can load by guid
If you dont work with AssetBundles you can move your meshes to Resources special subfolder and store path in AssetRef. In runtime load from resources by path
That seems like a good way if you want to load objects dynamically. But I’m trying to go the other way – the object will be loaded separately, and then a ScriptableRenderFeature will look up to see if it has any cached data about that mesh.
Create WeakRef struct storing the same guid or any type if uid, GlobalWeakReferenceManager and WeakRefRegistrator component that will register itself (or any other object with direct ref to it) on Awake and unregister OnDestroy.
Then your WeekRref can check existance of registered key in GlobalWeakReferenceManager
GlobalWeakReferenceManager is static class with dictionary
Still sounds like I’d need to attach some metadata manually instead of being able to extract it from the asset itself. Which makes it a bit awkward for a plugin. Anyways, I’ll noodle with it a bit more, but I think a custom AssetPostprocessor is probably the better way to go and just attach MonoBehaviours at import time instead of trying to do it ex post faco.