I have a simple singleton that is supposed to be setting up my background music and it’s returning null when I try and instantiate it. The script is attached to a GameObject with an audio clip attached to the source.
Script attached to the game object:
using UnityEngine;
using System.Collections;
public class GameMusic : MonoBehaviour
{
public static GameMusic _instance = null;
public static GameMusic getInstance {
get {
if (_instance == null) {
_instance = GameObject.FindObjectOfType<GameMusic> ();
DontDestroyOnLoad (_instance.gameObject);
}
return _instance;
}
}
void Awake ()
{
if (_instance == null) {
_instance = getInstance;
DontDestroyOnLoad (_instance);
} else if (this != _instance) {
Destroy (this.gameObject);
}
}
}
When trying to access the instance:
public class AdjustSettings : MonoBehaviour
{
public Texture settingsMenu;
public Font customFont;
public GUIStyle backButtonStyle = null;
public float hSliderValue = 0.0f;
public static GameMusic gameMusic;
public void OnGUI ()
{
GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), settingsMenu);
setupStyles ();
Settings ();
}
public void Settings ()
{
float buttonXPos = Screen.width / 2;
float buttonYPos = Screen.height / 2;
float buttonWidth = 100;
float buttonHeight = 30;
if (GUI.Button (new Rect (buttonXPos - 50, Screen.height - 50, buttonWidth, buttonHeight), "", backButtonStyle)) {
Application.LoadLevel ("SettingsMenu");
}
hSliderValue = GUI.HorizontalSlider (new Rect (buttonXPos, buttonYPos, 100, 100), hSliderValue, 0.0f, 1.0f);
gameMusic.audio.volume = hSliderValue;
}
public void setupStyles ()
{
if (backButtonStyle == null) {
backButtonStyle = new GUIStyle (GUI.skin.button);
backButtonStyle.font = customFont;
backButtonStyle.hover.textColor = Color.yellow;
backButtonStyle.fontSize = 20;
}
}
void Awake ()
{
gameMusic = GameMusic.getInstance;
if (gameMusic == null)
Debug.Log ("The gameMusic instance is set to null.");
}
}
Any help would be appreciated.
PS, This is my first time posting here so please forgive any omissions as I’m certain they are unintentional and thank you!
Well, it’s most likely that your AdjustSettings Awake is called before your GameMusic Awake function. Another possible reason is that you don’t have a GameMusic script attached to any object or that object is disabled.
You might want to either setup your script execution order in the settings or change the Awake method in AdjustSettings into Start which is called after all Awake has been called.
edit
I just had another look at your singleton code. I think it would be better to implement your Awake like this:
I’m pretty sure that inside of Awake while loading the scene FindObjectOfType can’t find the instance. It’s also not necessary since in Awake you can use “this”.
public class SingletonMonoBehaviour<T>:MonoBehaviour where T : MonoBehaviour
{
protected T instance = null;
public T Instance{
get{
if(instance == null)
{
instance = (T)FindObjectOfType(typeof(T));
}
return instance;
}
}
}
This is a basic implementation that does not prevent multi instances. You can still add a check in the Awake or OnEnable but it needs to be called if Awake is overriden:
This will only inform, some implementation destroy the extra one, well, I consider this wrong since if you have two instances, you cannot know which will be destroy. If one have data set in the inspector and one is added by mistake, the second may be run first and the first is destroyed and bam you are running a game that goes wrong and you do not know why… Just my view.
Then for any class you can use:
public class MyClass:Singleton<MyClass>{}
without rewriting the same code over many classes.
I really don’t see the need for singleton class here. I’v set up my background music basicly the same way you are trying to do it, but without any singleton stuff. So, since you have your Audio gameobject, why don’t just call DontDestroyOnLoad(gameObject) on Awake without any extra stuff? This way you can put your Audio gameobject on your main/start scene and it will be preserved over different scenes.
Then it’s easy to access the components of your Audio-object by using GameObject.FindWithTag(…)
Or even better I think is to use some kind of notification system to control volume etc. I’m using this: