- Home /
The question is answered, right answer was accepted
Help with Null Reference Exception please.
I'm getting a Null Reference exception on a line checking if a variable is null before copying it?
ANSWERED
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// A simple script that holds an array of audio clips so they can be triggered to play from an animation.
/// Use PlayClip( clipnumber ) to trigger the clip you would like played.
/// </summary>
class Anim_PlayAudio : MonoBehaviour
{
/// <summary>
/// Audio clip and priority data.
/// </summary>
[System.Serializable]
public class Audiodata
{
/// <summary>
/// A string containing a name for this clip for easy reference in the Inspector;
/// </summary>
public string name = "";
/// <summary>
/// <see cref="UnityEngine.AudioClip"/>
/// </summary>
public AudioClip audioClip = null;
/// <summary>
/// A <see cref="System.Int32"/> specifiying the priority of this AudioClip.
/// </summary>
public int priority = 16;
public Audiodata()
{
priority = 16;
}
}
/// <summary>
/// An array of <see cref="Anim_PlayAudio.AudioData"/> clips for playback.
/// </summary>
public Audiodata[] audioClips = null;
private AudioSource[] _sources = null;
void Awake()
{
if (audioClips == null)
{
ZCTDebug.EditorMessageBox( "Anim_PlayAudio on " + this.gameObject.name + ": no Audioclips in list to play. Please add one in the inspector.");
}
else
{
_sources = new AudioSource[audioClips.Length];
for (int i = 0; i < _sources.Length; i++ )
{
_sources[i] = new AudioSource();
if (audioClips[i] != null && audioClips[i].audioClip != null) _sources[i].clip = audioClips[i].audioClip;
else
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": Audio clip at index " + i + " is null!");
}
}
}
/// <summary>
/// Plays an audio clip from the audioClips array.
/// </summary>
/// <param name="clipNumber">The index of the clip to be played.</param>
void PlayClip(int clipNumber)
{
if (audioClips == null)
{
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": no Audioclips in list to play. Please add one in the inspector.");
}
if (clipNumber >= audioClips.Length)
{
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": Clip selected is out of range. Check your PlayClip( num ) function.");
}
if (clipNumber < 0)
{
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": Clip selected is out of range.\n PlayClip( num ) function. Value cannot be less than zero.");
}
if (_sources[clipNumber].clip.isReadyToPlay)
{
_sources[0].Play();
}
}
void PlayClipNamed(string clipDataName)
{
if (audioClips == null)
{
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": no Audioclips in list to play.\n Please add one in the inspector.");
}
bool _foundclip = false;
List<int>_indexes = new List<int>();
for(int i = 0; i < audioClips.Length; i++)
{
if ( audioClips[i].audioClip == null) ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": Clip selected does not exist. PlayClip( name ) function. The AudioClip specified is null.");
if ( audioClips[i].name == clipDataName) _foundclip = true;
_indexes.Add(i);
}
if (!_foundclip)
{
ZCTDebug.EditorMessageBox("Anim_PlayAudio on " + this.gameObject.name + ": Clip selected does not exist. PlayClip( name ) function. The audio clip specified wasn't found.");
}
else
{
foreach (int index in _indexes)
{
PlayClip(index);
}
}
}
}
The line generating the error was:
if (audioClips[i].audioClip != null) _sources[i].clip = audioClips[i].audioClip;
I'm including the output script referencing this one as well since it's useful to anyone reading this question in the future and in general.
using UnityEngine;
using UnityEditor;
using System.Collections;
/// <summary>
/// Debug replacement for comments only meant to be seen in the Unity Editor console.
/// </summary>
public static class ZCTDebug {
/// <summary>
/// Output a message to the console after checking to be sure the project is running in the Unity Editor.
/// </summary>
/// <param name="Output">A string containing the message to be echoed to the console. Recommended to begin with the name of the outputting Class.</param>
public static void Log (string Output) {
throw new System.Exception(Output);
}
/// <summary>
/// Output a modal popup message box to the editor user.
/// </summary>
/// <param name="Output">A string containing the message to be displayed to the user. Recommend including GameObject name and outputting Class name to aid in debugging.</param>
public static void EditorMessageBox(string Output)
{
#if UNITY_EDITOR
EditorUtility.DisplayDialog("Error!", Output, "Derp!", "");
#endif
}
}
_source is set to a new audioSource on the line immediately above. audioclips[i] has to exist in order to reach that line and the if statement is simply checking if it IS null, not trying to use it unless it isn't. I'm baffled. To me it reads like “if the paint is n't red put it on the wall, otherwise do nothing, I can't it's red. ???
Answer by whydoidoit · Oct 10, 2012 at 06:46 AM
Ok so there are a couple of things here:
You do null checks but don't put the code that requires the item to be non null in an else block, or return when the value was null.
You don't check whether audioClips[i] is null. Just because the array has a slot, it doesn't mean that slot is filled with an AudioClip - it will be null until initialised.
"You don't check whether audioClips[i] is null. Just because the array has a slot, it doesn't mean that slot is filled with an AudioClip - it will be null until initialised."
Updated to check if audioClips[i] is null, (Error was popping up when it wasn't, have to wait for my artist to come online to see if that fixed the error) I assumed when an Array is expanded in Inspector it would set all unspecified values to null (in the case of the first item(s)) or duplicate the last item in the array for others?
"You do null checks but don't put the code that requires the item to be non null in an else block, or return when the value was null."
There is another check for that lower down if a function tries to use it. The $$anonymous$$essageBox function pops up a modal Editor Dialogue message to the artist with a clear indication of what's wrong and where in the Scene.
That one edit fixed the error. Apparently the editor doesn't initialize audioClips[i] with a new AudioData() call when the array is expanded.
I really wonder what that thing does when you expand those arrays - and when it does it...
At least the fixed script is here if someone else needs it. We use it so an animation can trigger the playing of a sound or chorus of sounds (Using the same name for a group of clips)
Follow this Question
Related Questions
PlayClipAtPoint Qualify with Type Name 2 Answers
Why I am getting Negative Decibels (around -70dB) where Normal Speech around 60dB 2 Answers
How can I play audio clips depending on the players movement 0 Answers
AudioSource playing with delay for 1 step 0 Answers
Audio/c#/unity Can i control the duration by time ? 1 Answer