I keep some very frequently used animation assets in the Resources folder. These are loaded at the beginning of the game using Resouces.LoadAll() and references are cached inside a non-monobehavor class until the application terminates.
That is, I have a straight c# class used to cache references to a few resources that are used very frequently throughout the whole game.
The problem is that unity sometimes decides to unload the assets behind my back (I guess because it can’t find any references to them) and so the cached references become invalid.
Any ideas as to how I could tell unity to never unload these specific assets?
I’m not sure what kind of caching Unity does for this stuff, but if it’s based on you holding references to the data, could you just have an object that keeps references to all of these resources in a collection?
“An asset is deemed to be unused if it isn’t reached after walking the whole game object hierarchy, including script components. Static variables are also examined.”
incidentally I’m already keeping all my cached animation clips in a dictionary defined as a static variable:
//needs to be struct for dictionary to use this correctly as a key
//(otherwise we won't find any of our cached animations)
struct ClipName
{
public string spriteAnimationName;
public string clipName;
public ClipName(string spriteAnimationName, string clipName)
{
this.spriteAnimationName = spriteAnimationName;
this.clipName = clipName;
}
}
//cached data
public class Clip
{
public tk2dSpriteAnimation spriteAnimation;
public tk2dSpriteAnimationClip clip;
public Clip(tk2dSpriteAnimation spriteAnimation, tk2dSpriteAnimationClip clip)
{
this.spriteAnimation = spriteAnimation;
this.clip = clip;
}
}
//holds all cached data
static Dictionary<ClipName, Clip> cachedClips = new Dictionary<ClipName, Clip>();
this ensures I can just find a cached Clip based on its ClipName, you can see the dictionary is static.
isn’t this considered a static variable? weird, because the tk2dSpriteAnimation assets are being unloaded at random intervals.
That is indeed a static variable, but it is a collection. It is possible that Unity only considers direct individual static variables pointing to those references. This would truly be unfortunate. I wonder if any Unity employee could chime in on this. It’s possible this is a bug or just a poorly documented way that it is supposed to work.
That description from the documentation is less clear than I would hope. I suspect that by “game object hierarchy” they really mean the GameObject hierarchy, meaning that your variable needs to be somehow attached to a Unity GameObject, not just floating in a static class off in the ether. But I’m only speculating.
On a side note, if Unity is automatically trying to unload unused assets without you asking it to, that I suspect that may indicate that your game is getting a low memory warning or something similar. I wouldn’t expect Unity to do that entirely proactively. But again, I’m speculating.
wrote a bit of code to ensure there’s an gameobject with references to all the assets I’ve got cached, so they never expire
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// https://discussions.unity.com/t/819762/8
public class HoldResources : MonoBehaviour
{
static HoldResources instance;
public List<Object> holdResources;
static HoldResources Instance
{
get
{
if (instance != null)
{
return instance;
}
else
{
instance = ((GameObject)Instantiate(Resources.Load("holdResources"))).GetComponent<HoldResources>();
DontDestroyOnLoad(instance.gameObject);
return instance;
}
}
}
// Start is called before the first frame update
void Awake()
{
if (instance != null)
{
Debug.LogError("cannot create multiple instances");
}
}
public static void HoldResource(Object o)
{
if (!Instance.holdResources.Contains(o)) Instance.holdResources.Add(o);
}
}
just needs a prefab called “holdResources” with this component stored in the Resources folder.
call HoldResource to pass an object that will never get destroyed by unity.
not the most elegant but seemed like the safest option to me.