[Got it!]Classes keep spitting out null values (trying to play a looped song)

Hi.

In my game, I wrote a system where I can use 2 audio clips and sync them together to play one looped song, like in console games.

The song clips, as well as metadata for info and playback, are here:

using UnityEngine;
using System.Collections;

public class Song {

	public string gameTitle;			// Title of the track.
	public string sourceGame;			// Game the track comes from ("Original" for tracks composed for Feud).
	public bool introPlayed;			// Used for update.
	public bool canLoop;				// If it is a looping song.
	public AudioClip intro;				// The AudioClip containing the intro of the song.
	public AudioClip loop;				// The looping track.	
	public Sprite franchise;			// Franchise icon i.e. Mushroom for Mario songs.
	public string arrangement;			// Arrangement or Original?
	public string[] description;		// Array to contain the song's "description".
	public bool unlocked;				// For hidden songs: if they are unlocked or not.
	public bool isDefault;				// Default song (to check when Erasing Data).

	// Use this for initialization
	public Song (string title, string src, bool loopable, AudioClip beg, AudioClip loo, Sprite fran, string kind, string desc1, 
	                 string desc2, string desc3, string desc4, bool unhide, bool def) {
		gameTitle = title;
		sourceGame = src;
        canLoop = loopable;
		intro = beg;
		loop = loo;
		franchise = fran;
		arrangement = kind;
		description [0] = desc1;
		description [1] = desc2;
		description [2] = desc3;
		description [3] = desc4;
		unlocked = unhide;
		isDefault = def;
	}

	// If this is a hidden song, unlock it.
	public void unlock () {
		unlocked = true;
	}

	public void relock () {
		unlocked = false;
	}
}

So, this doesn’t throw any errors. In another class, I have a Song array with Song objects for every track in my game. Song.cs doesn’t inherit from MonoBehaviour because it’s just a container.

using UnityEngine;
using System.Collections;

public class SongSlots: MonoBehaviour {

    public Song[] songSlots;    // This array contains the entire music soundtrack and its metadata, using stuff from the Song class.

    public static SongSlots Instance{get; set;}

    void Awake()
    {
        songSlots = new Song[150]; // Set the array to the exact number of complete tracks in the game.
        // Set the metadata for ALL songs then return the instance of SongSlots.

[over 100 Song slots...]

        Instance = this;
    }

    // While the array is full already, get actual song count by using "unlocked". This is for the Sound Test.
    public int getTrueCount()
    {
        int count = 0;  // Song count will be here.
        // Calculate songs based on unlock status.
        for (int x = 0; x < songSlots.Length; ++x)
        {
            if (songSlots[x].unlocked)
            {
                // Increment "count" ONLY if songSlots[x].unlocked is true.
                ++count;
            }
        }
        return count;
    }
}

Again, no issues. Then I wrote this algorithm for playback:

using UnityEngine;
using System.Collections;

public class LoopBGM : MonoBehaviour
{
    public bool isSetUp;                     // To avoid constant resetting of playback to 0.
    public bool introPlayed;                 // To avoid playing the intro more than once.

    public static LoopBGM Instance { get; set; }

    void Awake()
    {
        Instance = this;
    }

    // Main src handler. Song object for the song. Assumes AudioSource is looped.
    public void playBGM(AudioSource src, Song track)
    {
        if (!introPlayed)
        {
            if (!isSetUp)
            {
                src.clip = track.intro;
                src.Play();
                isSetUp = true;
            }
            if (src.time == src.clip.length && track.canLoop == true && track.loop != null)
            {
                isSetUp = false;
                if (!isSetUp)
                {
                    src.clip = track.loop;
                    src.Play();
                    isSetUp = true;
                }
                introPlayed = true;   // Break out of if statement and leave src alone.
            }
        }
    }
}

Goes all right. Finally, I wrote a class to test this system in a test scene used to animate GameObjects.

using UnityEngine;
using System.Collections;

public class BGM_TEST : MonoBehaviour
{
    public AudioSource tst;
    public Song sng;
    public AudioClip clip;

    // Setup the AudioSource.
    void Awake()
    {
        tst = GetComponent<AudioSource>();
        sng = SongSlots.Instance.songSlots[0];
        clip = sng.intro;
    }
    void Update()
    {
        // Test while playing the main menu theme
        LoopBGM.Instance.playBGM(tst, sng);
    }
}

And I hit the test button above the Scene view. (Building crashes Unity 5.3 for now) The console keeps throwing null values and thus cannot play the intro clip in my Song object. I double checked the SongSlots array and everything is set up properly. AudioClips are set up using Resources.Load(“Song Path”) as AudioClip, and the OGG files are in a Resources folder. The Intro AudioClip never gets passed to my AudioSource component.

I’d really like to know why the heck it’s not working.

If there’s anything else you need to see, let me know.

The problem is your arrays.
1.) In your Song class, replace:

public string[] description with public string[] description = new string[4];

With arrays, you not only have to declare it with string[] description, but you must also initialize it to allocate memory. Therefore, when you try to set description[0] = ... later, it gives you an error because you don’t initialize it! You’ll also need to do that for all your other arrays.

If I were you, I would initialize it when you declare it.

If you’re using “song slots”, I’d use Lists so that you can change the size, instead of having to give it a fixed size.

If that doesn’t fix the problem, tell me what other errors you get, word for word.

Yep. I tried a variety of solutions and nothing works: it just won’t get the AudioClip.

I think it’s the List itself that returns null, because when I call it, that’s when it throws the error.

Since my List is in a Singleton class, how would one get data from it at runtime?