@tool class_name Sfx extends AudioStreamPlayer @export_enum("交互与效果音", "BGM", "场景背景音") var mode := "交互与效果音": set(value): mode = value notify_property_list_changed() # 当前播放状态注册;节点销毁前卸载 # TODO BGM 过程抑制场景音效;场景音效随玩家运动呼吸 (结合 Sfx2D) # 感应玩家移动:装饰音 var default_db := 0.0 # 只有 场景背景音 生效 var scene_loop := true var scene_autustart := true var scene_sense_player_mov := false func _ready() -> void: # autoplay = false bus = &"game_sfx" default_db = volume_db if mode == "场景背景音": autoplay = scene_autustart if Engine.is_editor_hint(): return finished.connect(_on_finished) func _on_finished() -> void: if mode == "场景背景音" and scene_loop: play() func resart(ease_duration := 1.0): easing_kill(ease_duration).tween_callback(play) # queue free 导致 sfx 无法播放,使用全局声源 func global_play() -> void: if stream: AudioManager.play_sfx(stream) # 注意:会导致 volume db 变化 func easing_kill(duration: float = 2.0) -> Tween: # stop with easing var tween = create_tween() if playing: tween.tween_property(self, "volume_db", -80.0, duration) tween.tween_callback(stop) # set volume_db back to default tween.tween_callback(func(): volume_db = default_db) return tween func _get_property_list() -> Array[Dictionary]: if mode != "场景背景音": return [] # # 只有 场景背景音 生效 # var scene_loop := true # var scene_autustart := true # var scene_sense_player_mov := false return [ { "name": "场景背景音配置项", "type": TYPE_NIL, "usage": PROPERTY_USAGE_GROUP, }, {"name": "自动开始", "type": TYPE_BOOL}, {"name": "循环播放", "type": TYPE_BOOL}, {"name": "感应玩家操作", "type": TYPE_BOOL} ] func _property_can_revert(property: StringName) -> bool: return property == "自动开始" or property == "循环播放" or property == "感应玩家操作" func _property_get_revert(property: StringName) -> Variant: if property == "自动开始" or property == "循环播放": return true elif property == "感应玩家操作": return false return null func _set(property: StringName, value: Variant) -> bool: if mode != "场景背景音": return false if property == "自动开始": scene_autustart = value return true elif property == "循环播放": scene_loop = value return true elif property == "感应玩家操作": scene_sense_player_mov = value return true return false func _get(property: StringName) -> Variant: if mode != "场景背景音": return null if property == "自动开始": return scene_autustart elif property == "循环播放": return scene_loop elif property == "感应玩家操作": return scene_sense_player_mov return null