So I have a ScriptableObject script for items and all the instances of it I am now storing in a folder that I marked as addressable and placed in an addressables group to load from code with “Addressables.LoadAssetsAsync()” specifying the label to be the label I set for the items. Now for each item, I have a list that shows what tiles that item drops from, and when I break blocks, I check through all the blocks in the items list (blocks is a derived script from the items script and I have separate arrays that stores each type of item, with one holding all the items) seeing if the specific tile that I am currently breaking is one of the tiles that the item drops from. This is all working from the editor, it returns the correct item that is supposed to drop from the tile, and there are no issues. The problem lies when I try to make a build and perform the same action as tiles no longer drop what they are meant to (they drop nothing). After some debugging I realized the problem is that when I compare the tile I need to find the corresponding item with using the items list that has what its meant to drop from (I compare the two tiles directly using the “==” operator), it appeared that the instance ID’s in the item’s tiles was different than that of the tile that I try to check for, even if they are the same, (i.e. I find that I am meant to drop dirt from the dirt tile, but the dirt item says that the dirt tile it has is different than the dirt tile that I am aiming at).
From my eyes this looks like something from addressables changing the instance ID to preserve the original scriptable object instance from what I understand when I did a bit of research, if anyone knows how to fix this please let me know.
I hope this is clear, if anyone needs further explanation I can provide more. If I am understanding any of this wrongly please correct me.
well instanceIDs are not persistent in the first place so its possible that the addressable loads a clone of a tile, thus a new instance ID. you should use the file guid instead (which is essentially an Addressable asset reference’s RuntimeKey) and make sure you set it at edit time. i dont think its possible to do it at runtime
UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(tile.GetInstanceID(), out string guid, out string fileId);
Whenever any Asset or Object is loaded, it is given a new instance id. This is true in the editor as with the player. So you may be seeing something different. (note in editor, the loaded assets may persist unless they are unloaded and reloaded through the resources api between plays, so the same instance may persist as you develop.
Is there any common identifier you can think of by which an object that has been instantiated from an AssetReference can be reliably matched back to that AssetReference after the fact?
The scenario I am looking at and struggling with is a material matching system to be used for hot swapping materials. I have a scriptable object with a list of pairs of AssetReferenceT - one for the original mat and one for the mat to swap it to on a particular event. The entries in this list are populated with the relevant materials (which themselves are marked addressable, as are the prefabs that use them), and the swapping system works by going through the prefab instance’s renderers and gathering all the materials and then doing a lookup of original mat to swap mat from a dictionary prepared at the start. The problem is that the dictionary basically needs to be conjured from loading every one of the pairs into memory just to get at their .Asset to get the material reference, and I really don’t want to have every possible material pulled out of the bundles into memory all at once, incurring a high memory and startup load cost. Ideally, I would want the system to work as follows:
Spawn prefab instances as per normal and allow Addressables to load the prefab and just those materials (i.e. the ones corresponding to some subset of the “original” mats) for that prefab. This part does work as expected
When the swap event is triggered, have some way of “looking up” the correct AssetReference pair from my SO list for a given material belonging to that prefab instance. Ideally some sort of hash int identifier or similar would be perfect
Load just the corresponding “swap” AssetReference matching asset and apply it
Currently the only way I have been able to make it work is by converting the AssetReference pairs to the costly Material pairs that forces it all to be in memory at once. I have experimented with saving instanceID at editor time into the SO, but as you noted above, this does not stay fixed in the bundle but gets reassigned a new instanceID whenever you load the bundle. While the instantiated materials on the prefabs do end up also taking on those same instanceIDs, that still does not help with the need to subsequently identify the bundle from the material later on. Similarly, ComputeCRC also changes between runs, presumably because that is factoring instanceID into the hash I would guess.
I have two more possible solutions I can think of. One is to look into whether Addressables load has some sort of pub/sub event I can subscribe to that listens to the prefab getting instantiated and then records the session-specific instanceID at that point. Another is to come up with my own hash code method for Material that attempts to produce consistent hashes regardless of any instance resequencing that occurs during the asset load. But if there’s an easier alternative to these, I’d love to hear it.