I find myself often doing this kind of pattern:
AudioSource cachedAudioSource = null;
AudioSource audioSource
{
get
{
if( cachedAudioSource == null )
{
cachedAudioSource = (AudioSource)GetComponent( typeof( AudioSource ) );
}
return cachedAudioSource;
}
}
That gets me the components the first time I need them; no more, no less.
So I thought I could use generics to clean up this code a little bit:
public static void GetComponentIfNull< T >( MonoBehaviour that, ref T cachedT ) where T : Component
{
if( cachedT == null )
{
cachedT = (T)that.GetComponent( typeof( T ) );
if( cachedT == null )
{
Debug.LogWarning( "GetComponent of type " + typeof( T ) + " failed on " + that.name, that );
}
}
}
Which results in my client code looking a little neater:
AudioSource cachedAudioSource = null;
AudioSource audioSource
{
get
{
Util.GetComponentIfNull( this, ref cachedAudioSource );
return cachedAudioSource;
}
}
But the problem is, it doesn't seem to work. Specifically, the check to see if cachedT == null in the generic function seems to think the ref pointer to my T object is NOT null (even if I explicitly set it to null, which shouldn't be necessary), yet if I check to see if audioSource == null, that returns true.
More specifically, it seems to only happen with built in types that don't derive from MonoBehaviour, i.e. audio sources colliders, etc. I've used this script successfully before for my own scripts.
Is this just something I can't work around due to the fact that apparently nulls aren't real nulls?
Edit: Thanks to @SpikeX for pointing out that Component.audio basically does what I want with my specific example, but I'm still somewhat curious as to why it doesn't work.