Trying to change Clip of Audio Source at runtime causes NullReferenceException

Hello,

I am trying to change Clip of AudioSource with the following script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CustomStructs;

//[RequireComponent(typeof(AudioSource))]//Needed for controlling audio
//Public class to manage ListMembers
public class ListManager : MonoBehaviour
{
    //Public Variable Declaration
    public float rotationSpeed = 4;//Speed to rotate ListMember
    public bool audioAssigned = false;//Whether audioClip is assigne or not

    //Private Variable Declaration
    private int Id;//Id of current ListManager Instance, currently unused
    private bool debug = false;//Tmp variable
    private AudioSource audioSource;//Audio Source tied to curr ListManager Instance


    // Start is called before the first frame update
    void Start()
    {
        //Assign audio source
        audioSource = this.gameObject.GetComponent<AudioSource>();
    }

    // Update is called once per frame
    private void Update()
    {
        //Tmp code
        if (!debug)
        {
            Debug.Log(this.name + " id:" + Id.ToString());
            debug = true;
        }

        //Rotate curr GameObject to animate
        Vector3 targetRotation = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y + rotationSpeed, transform.eulerAngles.z);
        transform.rotation = Quaternion.Euler(targetRotation);
    }


    //public method to read curr ListManager Instance's ID, currently unused
    public int GetId()
    {
        return Id;
    }


    //public method to set curr ListManager Instance' ID
    public void SetId(int id)
    {
        this.Id = id;
    }

    //Public Method to Set AudioClip of curr ListManager Instance
    public void SetAudioClip(AudioClip audio)
    {
        audioSource.clip = audio;
        audioAssigned = true;
    }
}

But, when I try to call SetAudioClip from following script at line 79, I get a NullReferenceException.(Commented code contains failed attempts)

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
using CustomStructs;


//Public Class to Controll Camera and act as SceneManager
public class CameraController : MonoBehaviour
{
    //Public Variable Declaration
    //public AudioClipDictionaryList[] audioClipsList;//Temporary List for making dictionary
    //public Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();//Dictionary with name as key and audio clip as value
    public List<AudioClip> audioClips;
    public List<GameObject> listMembers;//Reference to all ListMembers
    public Camera mainCamera;
    public Button m_LeftButton, m_RightButton;//Camera movement controll buttons
    public int transitionDis = 40;//Transition Distance for Camera
    public float transitionSpeed = 1;//Transition Speed for Camera
    public int totalListIds = 0;//For keeping track of total ListMembers

    //Private Variable Declaration
    private Vector3 mainCamCurrPos;//Keep track of current Camera Position, may not be uptodate
    private float mainCamPosCurrX;//Current X position of Camera, may not be uptodate
    private Vector3 mainCamtargetPos;//Store target position of Camera when moving
    private float mainCamPosTargetX;//Store target X position of Camera when moving
    private bool camMoving = false;//Used to prevent movement calls when Camera is already moving


    // Start is called before the first frame update
    void Start()
    {
        //Convert AudioClip List into Dictionary
        //foreach (AudioClipDictionaryList i in audioClipsList)
        //{
        //    audioClips.Add(i.name, i.audioClip);
        //}

        //Iterate over all List Members for setup
        for (int i = 0; i < listMembers.Count; i++)
        {
           ListManager currListMember = listMembers[i].GetComponent<ListManager>();

            if (currListMember == null)
            {
                throw new Exception("GameObject does not have ListManager assigned to it:" + listMembers[i].name);
            }

            //Set Id of List Member to keep track of total Members
           currListMember.SetId(totalListIds + 1);
           totalListIds += 1;

            //Get List Member name for setting appropriate audioclip to list member
            //string ListItemName = currListMember.name.TrimEnd("Rig".ToCharArray());
            //Debug.Log(currListMember.name + " name set to " + ListItemName);

            //Assign appropriate audioclip
            // if (audioClips.ContainsKey(ListItemName))
            // {
            //     //AudioClip currAudioClip;
            //     AudioClip currAudioClip;
            //     audioClips.TryGetValue(ListItemName, out currAudioClip);
            //     currListMember.SetAudioClip(currAudioClip);
            //     Debug.Log("Audio Clip assigned to " + ListItemName);
            // }

            // //Log Error if no matching audioclip is found for a List Member
            // else
            // {
            //     Debug.LogError(ListItemName + " does not have audio clip assigned.");
            // }

            foreach(AudioClip clip in audioClips)
            {
                if (clip.name == listMembers[i].name.TrimEnd("Rig".ToCharArray()))
                {
                    Debug.Log("Working Befor...");
                    currListMember.SetAudioClip(clip);
                    Debug.Log("Working After...");
                }
            }

            if (!currListMember.audioAssigned)
            {
                throw new Exception("Audio Clip not found for:" + listMembers[i].name);
            }

        }

        //Assign MainCamera value
        mainCamera = Camera.main;

        //Assign ClickListeners for Camera Control Buttons
        m_LeftButton.onClick.AddListener(OnLeftButtonClick);
        m_RightButton.onClick.AddListener(OnRightButtonClick);
    }
//..other code here...
}

How should I do this correctly?

I am more than happy to provide more information if you need.

Hey, you mentioned the NullReferenceException occurs in CameraController on line 79
which would mean currListMember == null, and that’s unlikely given that’s caught in line 45.
So I’m guessing it’s occuring on ListManager on line 59; on ‘SetAudioClip’ where ‘audioSource’ could be null.

Stab in the dark, but if I read this right; ListManager assigns it’s audioSource on Start,
while CameraController also calls the ‘SetAudioClip’ method on Start.
Leading to a potential race condition:
Without setting script execution order explicitly there is no way of knowing which one gets executed first,
this could lead to CameraController calling ‘SetAudioClip’ before ListManager’s Start occurs.

Try fetching ListManager’s audioSource on Awake(), ensuring it gets executed first.
(Which is generally a good habbit)

I will try that as soon as possible and now that you have pointed it out, I think it’s a cause of race condition only. Thanks for the help.