extends Node2D @export var binded_rock: Rock @export var binded_volumn: PlayerTriggerVolumn var _rock : Rock var _volumn : PlayerTriggerVolumn func _ready() -> void: _rock = binded_rock if binded_rock != null else _find_first_rock(self) _volumn = binded_volumn if binded_volumn != null else _find_first_volumn(self) if not _volumn or not _rock: return _volumn.player_entered.connect(_on_rock_start_shake,CONNECT_ONE_SHOT) func _on_rock_start_shake(player: Player) -> void: if not _rock: return _rock.start_shaking() $Timer.start() $Timer.timeout.connect(_on_rock_falling) func _on_rock_falling() -> void: _rock.stop_shaking() _rock.start_falling() ## ================================ ## 查找工具函数(强类型) ## ================================ func _find_first_rock(root: Node) -> Rock: var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is Rock) return found as Rock func _find_first_volumn(root: Node) -> PlayerTriggerVolumn: var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is PlayerTriggerVolumn) return found as PlayerTriggerVolumn func _find_first_child_matching(root: Node, predicate: Callable) -> Node: for child: Node in root.get_children(): # predicate.call() 返回值在类型系统里可能是 Variant,所以别用 := 推断 var ok: bool = bool(predicate.call(child)) if ok: return child var deeper: Node = _find_first_child_matching(child, predicate) if deeper != null: return deeper return null