- Home /
MonoBehaviour Inheritance, Singletons and Generics
I'm trying to set up an AudioManager that can be reused across projects without having to rewrite the key pieces each time. The problem I'm having is that if I extend this AudioManager (ie, MyProjectAudioManager), other classes are unable to access additional features added in the subclass.
Here are the implementation details:
First, I have a generic Singleton class that I use for Managers like this:
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// ... singleton implementation
// similar to http://wiki.unity3d.com/index.php?title=Singleton#Generic_Based_Singleton_for_MonoBehaviours
public static T instance;
}
Then I subclass that for my generic audio manager, where T is an enum of the available audio files. (actually I have a subclass, PersistentSingleton, in between, which makes the singleton persist across scenes).
public abstract class AudioManager<T> : Singleton<AudioManager<T>>
{
public abstract IAudioLoader<T> audioFiles { get; }
public void PlayAudio(T audioType)
{
AudioClip clip = audioFiles.GetAudioClip(audioType);
// play the clip!
}
}
I'm trying to use the generic here so that I can use an enum to specify which audio files are available on a given project, ie
public enum MyProjectAudioType
{
Blip,
Bloop,
...
}
And the same type is supplied to the generic loader class, so that it is in charge of loading the audio file from Resources:
public class MyProjectAudioLoader : IAudioLoader<MyProjectAudioType>
{
public AudioClip GetAudioClip(MyProjectAudioType type)
{
// check for cached version, otherwise load from Resources
}
}
Finally, I have my specific project implementation of the AudioManager, which ends up being pretty simple, as it just ties together the specific project audio type and allows me to attach the manager to a GameObject to be used in the scene. (The actual implementation has another subclass in between that differentiates between a Music Manager or Sound Effects Manager, but that doesn't seem related to my problem)
public class MyProjectAudioManager : AudioManager<MyProjectAudioType>
{
public MyProjectAudioLoader myAudioFilesLoader;
public override IAudioLoader<MyProjectAudioType> audioFiles { get { return myAudioFilesLoader; } }
public void MyCustomFunction() { ... } // any sort of custom functionality
}
Then for each project, its just a matter of defining the available audio clips, and calling MyProjectAudioManager.instance.PlayAudio(MyProjectAudioType.Blip); The system manages caching clips, pooling audio sources, unloading unused resources under heavy load, etc.
Now, the problem is, if I define a custom function within the specific MyProjectAudioManager, I can't seem to access it through the singleton instance. (ie, MyProjectAudioManager.instance.MyCustomFunction(); ). Maybe it has to do with the fact that the AudioManager base class is inheriting from the Singleton, and not the project specific audio manager. But I don't understand why that would affect it like this, and I'm not really sure how to resolve the issue. Any suggestions on whats going on and how to fix it? Alternative solutions that would still allow me to reuse base classes without having to rewrite it on every project?
Answer by chirhotec · Apr 08, 2014 at 08:45 AM
Finally solved this by changing some of the class defintions:
public abstract class AudioManager<M, T> : Singleton<M> where M : MonoBehaviour { ... }
public class MyProjectAudioManager : AudioManager<MyProjectAudioManager,MyProjectAudioType> { ... }
Your answer
Follow this Question
Related Questions
C# Inheriting from MonoBehaviour but still be able to instantiate with new()? How should I do this? 2 Answers
Extending a Singleton base class (UJS) (?) 2 Answers
MonoBehaviour pseudo-singleton with C# generics 1 Answer
Generic MonoBehaviour with nested class serialization issue 1 Answer
How can I return a GameObject? 1 Answer