Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Audio Trying to change Clip of Audio Source at runtime causes NullReferenceException

Discussion in 'Audio & Video' started by Ved_Prajapati, Apr 30, 2021.

  1. Ved_Prajapati

    Ved_Prajapati

    Joined:
    May 28, 2019
    Posts:
    3
    Hello,

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

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using CustomStructs;
    5.  
    6. //[RequireComponent(typeof(AudioSource))]//Needed for controlling audio
    7. //Public class to manage ListMembers
    8. public class ListManager : MonoBehaviour
    9. {
    10.     //Public Variable Declaration
    11.     public float rotationSpeed = 4;//Speed to rotate ListMember
    12.     public bool audioAssigned = false;//Whether audioClip is assigne or not
    13.  
    14.     //Private Variable Declaration
    15.     private int Id;//Id of current ListManager Instance, currently unused
    16.     private bool debug = false;//Tmp variable
    17.     private AudioSource audioSource;//Audio Source tied to curr ListManager Instance
    18.  
    19.  
    20.     // Start is called before the first frame update
    21.     void Start()
    22.     {
    23.         //Assign audio source
    24.         audioSource = this.gameObject.GetComponent<AudioSource>();
    25.     }
    26.  
    27.     // Update is called once per frame
    28.     private void Update()
    29.     {
    30.         //Tmp code
    31.         if (!debug)
    32.         {
    33.             Debug.Log(this.name + " id:" + Id.ToString());
    34.             debug = true;
    35.         }
    36.  
    37.         //Rotate curr GameObject to animate
    38.         Vector3 targetRotation = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y + rotationSpeed, transform.eulerAngles.z);
    39.         transform.rotation = Quaternion.Euler(targetRotation);
    40.     }
    41.  
    42.  
    43.     //public method to read curr ListManager Instance's ID, currently unused
    44.     public int GetId()
    45.     {
    46.         return Id;
    47.     }
    48.  
    49.  
    50.     //public method to set curr ListManager Instance' ID
    51.     public void SetId(int id)
    52.     {
    53.         this.Id = id;
    54.     }
    55.  
    56.     //Public Method to Set AudioClip of curr ListManager Instance
    57.     public void SetAudioClip(AudioClip audio)
    58.     {
    59.         audioSource.clip = audio;
    60.         audioAssigned = true;
    61.     }
    62. }
    63.  
    But, when I try to call SetAudioClip from following script at line 79, I get a NullReferenceException.(Commented code contains failed attempts)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6. using CustomStructs;
    7.  
    8.  
    9. //Public Class to Controll Camera and act as SceneManager
    10. public class CameraController : MonoBehaviour
    11. {
    12.     //Public Variable Declaration
    13.     //public AudioClipDictionaryList[] audioClipsList;//Temporary List for making dictionary
    14.     //public Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();//Dictionary with name as key and audio clip as value
    15.     public List<AudioClip> audioClips;
    16.     public List<GameObject> listMembers;//Reference to all ListMembers
    17.     public Camera mainCamera;
    18.     public Button m_LeftButton, m_RightButton;//Camera movement controll buttons
    19.     public int transitionDis = 40;//Transition Distance for Camera
    20.     public float transitionSpeed = 1;//Transition Speed for Camera
    21.     public int totalListIds = 0;//For keeping track of total ListMembers
    22.  
    23.     //Private Variable Declaration
    24.     private Vector3 mainCamCurrPos;//Keep track of current Camera Position, may not be uptodate
    25.     private float mainCamPosCurrX;//Current X position of Camera, may not be uptodate
    26.     private Vector3 mainCamtargetPos;//Store target position of Camera when moving
    27.     private float mainCamPosTargetX;//Store target X position of Camera when moving
    28.     private bool camMoving = false;//Used to prevent movement calls when Camera is already moving
    29.  
    30.  
    31.     // Start is called before the first frame update
    32.     void Start()
    33.     {
    34.         //Convert AudioClip List into Dictionary
    35.         //foreach (AudioClipDictionaryList i in audioClipsList)
    36.         //{
    37.         //    audioClips.Add(i.name, i.audioClip);
    38.         //}
    39.  
    40.         //Iterate over all List Members for setup
    41.         for (int i = 0; i < listMembers.Count; i++)
    42.         {
    43.            ListManager currListMember = listMembers[i].GetComponent<ListManager>();
    44.  
    45.             if (currListMember == null)
    46.             {
    47.                 throw new Exception("GameObject does not have ListManager assigned to it:" + listMembers[i].name);
    48.             }
    49.  
    50.             //Set Id of List Member to keep track of total Members
    51.            currListMember.SetId(totalListIds + 1);
    52.            totalListIds += 1;
    53.  
    54.             //Get List Member name for setting appropriate audioclip to list member
    55.             //string ListItemName = currListMember.name.TrimEnd("Rig".ToCharArray());
    56.             //Debug.Log(currListMember.name + " name set to " + ListItemName);
    57.  
    58.             //Assign appropriate audioclip
    59.             // if (audioClips.ContainsKey(ListItemName))
    60.             // {
    61.             //     //AudioClip currAudioClip;
    62.             //     AudioClip currAudioClip;
    63.             //     audioClips.TryGetValue(ListItemName, out currAudioClip);
    64.             //     currListMember.SetAudioClip(currAudioClip);
    65.             //     Debug.Log("Audio Clip assigned to " + ListItemName);
    66.             // }
    67.  
    68.             // //Log Error if no matching audioclip is found for a List Member
    69.             // else
    70.             // {
    71.             //     Debug.LogError(ListItemName + " does not have audio clip assigned.");
    72.             // }
    73.  
    74.             foreach(AudioClip clip in audioClips)
    75.             {
    76.                 if (clip.name == listMembers[i].name.TrimEnd("Rig".ToCharArray()))
    77.                 {
    78.                     Debug.Log("Working Befor...");
    79.                     currListMember.SetAudioClip(clip);
    80.                     Debug.Log("Working After...");
    81.                 }
    82.             }
    83.  
    84.             if (!currListMember.audioAssigned)
    85.             {
    86.                 throw new Exception("Audio Clip not found for:" + listMembers[i].name);
    87.             }
    88.  
    89.         }
    90.  
    91.         //Assign MainCamera value
    92.         mainCamera = Camera.main;
    93.  
    94.         //Assign ClickListeners for Camera Control Buttons
    95.         m_LeftButton.onClick.AddListener(OnLeftButtonClick);
    96.         m_RightButton.onClick.AddListener(OnRightButtonClick);
    97.     }
    98. //..other code here...
    99. }
    100.  
    How should I do this correctly?
     
  2. Ved_Prajapati

    Ved_Prajapati

    Joined:
    May 28, 2019
    Posts:
    3
    I am more than happy to provide more information if you need.
     
  3. DriesVienne

    DriesVienne

    Joined:
    Jun 22, 2013
    Posts:
    27
    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)
     
  4. Ved_Prajapati

    Ved_Prajapati

    Joined:
    May 28, 2019
    Posts:
    3
    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.