I have a script with a whole bunch of objects, each one is one of three types, that is defined as class in the script, when I call a method of one of the objects in the script, I sometimes get a null reference exception, literally the same line of code works fine one moment and then causes problems the next…here’s my code…
Assigning the reference to the SoundController script SoundController soundController = GameObject.Find("ScenePersistentObject").GetComponent<SoundController>();
An example of where it sometimes crashes
try
{
guiController.OutputText("\t <color=#500050D0>DEBUG: Rocket has entered stasis</color>");
soundController.AcceptSound.Play();
}
catch
{
Debug.Log("NULL REFERENCE EXCEPTION WHEN CALLING ACCPETSOUND.PLAY()");
Debug.Log("GameObject name is: " + soundController.gameObject.name);
//This line is fine, so the null reference exception isn't the reference to soundController
Debug.Log("Accept sound type is: " + soundController.AcceptSound.GetType().ToString());
//This line causes a problem (sometimes), so it must be something to do with the AcceptSound object(?)
}
(sorry for just dumping all my code in this next one, not sure what is and isn’t relevant)
SoundController Script
using UnityEngine;
using System;
using System.Collections;
//The purpose of this script is to play sound effects when other scripts call the appropriate method
public class SoundController : MonoBehaviour {
public GameSound EngineSound;
public GameSound ExplosionSound;
public InterfaceSound ErrorSound;
public InterfaceSound AcceptSound;
public InterfaceSound WhiteNoiseSound;
public InterfaceSound SegmentLoadSound;
public InterfaceSound LoadInterfaceSound;
public InterfaceSound TypingSound;
public VoiceSound CountdownSound;
public VoiceSound LiftOffSound;
public VoiceSound ZeroGSound;
public VoiceSound MoonLandingSound;
//These must be public so they can be accessed by other scripts
public AudioSource EngineSoundSource;
public AudioSource ExplosionSoundSource;
public AudioSource ErrorSoundSource;
public AudioSource AcceptSoundSource;
public AudioSource WhiteNoiseSoundSource;
public AudioSource SegmentLoadSoundSource;
public AudioSource LoadInterfaceSoundSource;
public AudioSource TypingSoundSource;
public AudioSource CountdownSoundSource;
public AudioSource LiftOffSoundSource;
public AudioSource ZeroGSoundSource;
public AudioSource MoonLandingSoundSource;
//These must be public so they can be assigned via the inspector
void Start()
{
SetVolumes(); //Sets the volume on each sound object to the corresponding value in the DataMemory script
}
public void SetVolumes()
{
EngineSound = new GameSound(EngineSoundSource);
ExplosionSound = new GameSound(ExplosionSoundSource);
ErrorSound = new InterfaceSound(ErrorSoundSource);
AcceptSound = new InterfaceSound(AcceptSoundSource);
WhiteNoiseSound = new InterfaceSound(WhiteNoiseSoundSource);
SegmentLoadSound = new InterfaceSound(SegmentLoadSoundSource);
LoadInterfaceSound = new InterfaceSound(LoadInterfaceSoundSource);
TypingSound = new InterfaceSound(TypingSoundSource);
CountdownSound = new VoiceSound(CountdownSoundSource);
LiftOffSound = new VoiceSound(LiftOffSoundSource);
//These must be passed the sound source, the objects are reinitilaized when the volumes are change in the options menu, so the sound sources cannot be assigned via the editor using the serializable attribute
}
void Update()
{
if (Time.timeScale != 1)
{
CountdownSound.Stop(); //Can't have the countdown voice play if timescale isn't 1, wont sync with countdown timer
}
}
}
public abstract class AudioType
{
protected AudioSource SoundEffect;
protected DataMemory dataMemory; //Holds the script containing volume variables
public AudioType(AudioSource soundEffectToSet)
{
SoundEffect = soundEffectToSet;
dataMemory = GameObject.Find("ScenePersistentObject").GetComponent<DataMemory>();
//sets the script to the component of the object it is attached to
}
public void Play()
{
try {SoundEffect.Play();}
catch {Debug.Log("Can't access audiosource: " + GetType().ToString());}
}
public void Stop()
{
try {SoundEffect.Stop();}
catch {Debug.Log("Can't access audiosource: " + GetType().ToString());}
}
public bool isPlaying()
{
try
{
if (SoundEffect.isPlaying)
{return true;}
else
{return false;}
}
catch {Debug.Log("Can't access audiosource: " + GetType().ToString());}
return false;
}
//The above three methods allow AudioType.Method, instead of AudioType.AudioSource.Method
}
public class GameSound : AudioType
{
public GameSound(AudioSource soundEffectToSet) : base (soundEffectToSet)
{//Must have the same paramaters as the constructor from the base class
SoundEffect.volume = dataMemory.gameVolume;
//Sets the volume of this objec's sound source to the corresponding variable
}
}
public class InterfaceSound : AudioType
{
public InterfaceSound(AudioSource soundEffectToSet) : base(soundEffectToSet)
{//Must have the same paramaters as the constructor from the base class
SoundEffect.volume = dataMemory.interfaceVolume;
//Sets the volume of this objec's sound source to the corresponding variable
}
}
public class VoiceSound : AudioType
{
public VoiceSound(AudioSource soundEffectToSet) : base(soundEffectToSet)
{//Must have the same paramaters as the constructor from the base class
SoundEffect.volume = dataMemory.voiceOverVolume;
//Sets the volume of this object's sound source to the corresponding variable
}
}
There doesn’t seem to be any pattern as to when it does and doesn’t crash, but restarting it always seems to fix it, until it causes issues again, how is the code not behaving in the same way each time, is something making one of the reference variables to be, I don’t know forgotten or something?
Any input would be appreciated ![]()
Thanks,
Fred T.A