### sounds.gd ### class_name Sounds extends Node # Attach this to whatever scene you want @export var soundboard : SoundBoard @export var lazy : bool = true func _ready() -> void: if soundboard: if not lazy: soundboard.setup(self) elif "ready" in soundboard.streams: soundboard.setup(self, "ready") func play(type: String): if soundboard: return soundboard.play(self, type) static func _play_global(stream, position) -> void: Engine.get_main_loop().get_current_scene().add_child(stream) if position: stream.global_position = position stream.play(0) await stream.finished stream.queue_free() func play_global(type: String): if soundboard: var clone = soundboard.clone(self, type) if clone: Sounds._play_global(clone, self.global_position) func stop(type): if soundboard: soundboard.stop(self, type) func has(type: String) -> bool: if soundboard: return soundboard.has(type) return false ### sound_board.gd ### class_name SoundBoard extends Resource @export var streams : Dictionary[String, AudioStream] = {} # Config vars should be in the format: # "type:property" : "value" # "ready:max_distance" : "25.0" # "attack:volume_db" : "-10.0" @export var config : Dictionary[String, String] = {} @export var default_distance := 10.0 func setup(target : Node, type = null) -> void: if type: _setup(target, type) else: for _type in self.streams: _setup(target, _type) func _setup(target : Node, type: String) -> void: # Create 2d or 3d automatically var player = AudioStreamPlayer3D.new() if target is Node3D else AudioStreamPlayer2D.new() player.name = "%s_sounds" % type player.stream = self.streams[type] player.max_distance = default_distance for key in self.config: var parts = key.split(":") if parts[0] == type: player.set(parts[1], self.config[key]) if type == "ready": player.autoplay = true target.add_child(player) func play(target : Node, type: String): if self.streams.has(type): var node = target.get_node_or_null("%s_sounds" % type) if not node: self.setup(target, type) node = target.get_node("%s_sounds" % type) node.play(0) return node func stop(target : Node, type: String): if not type: for _t in self.streams: target.get_node("%s_sounds" % _t).stop() if self.streams.has(type): target.get_node("%s_sounds" % type).stop() func clone(target: Node, type: String) -> Variant: if self.streams.has(type): var node = target.get_node_or_null("%s_sounds" % type) if not node: self.setup(target, type) node = target.get_node("%s_sounds" % type) return node.duplicate() return null func has(type: String) -> bool: return self.get(type) != null
or share this direct link: