I have an array of sounds that trigger, one at a time, from an array of loads. I am exporting six values to fill this array but don't need all six slots each time (using this code across multiple objects that won't all need six sound files). Essentially, if a "slot" in the array is empty, I want to remove it before the load. (Think the piano sounds at Bioshock's opening menu).

I have tried loops to remove empty strings and other things and it continues to plug in the empty values. I don't want to have to write this code for every item that uses it. What am I missing?

extends Area2D


var _can_play = false

export var _sound1 : String
export var _sound2 : String
export var _sound3 : String
export var _sound4 : String
export var _sound5 : String
export var _sound6 : String
var _preloadArray = [_sound1,_sound2,_sound3,_sound4,_sound5,_sound6]
var _soundArray = []


func _ready(): ## here the array fills with exported values, ignore the prompt, that's working
	_soundArrayFill()
	_prompt.visible = false
	

func _process(_delta): ## listen for input every frame
	_soundTrigger()


func _soundTrigger(): ## listen for input
	if Input.is_action_just_pressed("_interact"):
		if _can_play:
			_soundLoader()
			$AudioStreamPlayer2D.play()
	
	
	if Input.is_action_just_released("_interact"): ## if array empty on button release, reload it
		if _soundArray.empty():
			_soundArrayFill()


func _soundLoader(): ## load sound from array
	var _newSound = _soundArray.pop_front()
	var _loading = load(_newSound)
	$AudioStreamPlayer2D.set_stream(_loading)


func _soundArrayFill(): ## fill array if empty and check for empty values (what am i doing wrong here?)
	randomize()
	_preloadArray.shuffle()
	_soundArray = _preloadArray
	
	for i in _soundArray:
		if i == null:
			_soundArray.erase(i)
  • Rule #1: Don't remove elements from an Array while looping through it.
    Rule #2: See Rule #1.

Rule #1: Don't remove elements from an Array while looping through it.
Rule #2: See Rule #1.

Thanks @DaveTheCoder for the advice. I made a separate array as a reference and checked the values for empties before loading the actual sound array, therefore not doing the removal while looping.

Here it is now working!

extends Area2D


var _can_play = false

export var _sound1 : String
export var _sound2 : String
export var _sound3 : String
export var _sound4 : String
export var _sound5 : String
export var _sound6 : String
var _preArray = []
var _soundArray = []


func _ready():  ## fill array and check for errors at ready
	_arrayLoading()
	

func _process(_delta): ## listen for input per frame
	_soundTrigger()


func _soundTrigger(): ### accept player input to trigger sound
	if Input.is_action_just_pressed("_interact"):
		if _can_play:
			_soundLoader() ## load new sound each input
			$AudioStreamPlayer2D.play()
	
	if Input.is_action_just_released("_interact"):
		if _soundArray.empty(): ## if array is empty on button release, refill it
			_arrayLoading()


func _soundLoader(): ## sound loader and shuffling function
	randomize()
	_soundArray.shuffle()
	var _newSound = _soundArray.pop_front()
	var _nowLoaded = load(_newSound)
	$AudioStreamPlayer2D.set_stream(_nowLoaded)


func _arrayLoading(): ## array fill and debug function
	_preArray = [_sound1,_sound2,_sound3,_sound4,_sound5,_sound6]
	
	for i in _preArray:
		if i != "":
			_soundArray.append(i)