You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Animator的animation_finished信号绑定多Area2D后场景切换异常的解决咨询

问题分析与解决方案

问题根源

你遇到的核心问题是所有Area2D都绑定了同一个Animator的animation_finished信号,导致过渡动画结束时,四个Area2D的_on_transition_animation_finished回调会依次执行,最终只有最后一次场景切换生效;同时Autoload的目标信息会被多个回调反复覆盖,也是因为所有绑定的脚本都在修改它。


方案一:触发过渡的Area2D临时绑定信号(推荐)

不让所有Area2D提前绑定信号,只在玩家进入并触发过渡时,让当前Area2D临时监听动画结束信号,完成切换后立即解除绑定,避免其他Area2D干扰。

修改后的Area2D脚本:

extends Area2D

var entered = false
@export var room = ""
var animation_playing = false
@export var xPosition = 0
@export var yPosition = 0
var player
var transition_animator = null  # 缓存过渡动画节点

func _on_body_entered(body: PhysicsBody2D):
    entered = true
    player = body
    # 获取主场景的过渡动画节点
    transition_animator = get_parent().$Transition

func _on_body_exited(body):
    entered = false
    # 退出时解除信号绑定,避免残留
    if transition_animator != null:
        transition_animator.animation_finished.disconnect(_on_transition_animation_finished)
    animation_playing = false

func _process(delta):
    if entered == true and animation_playing == false:
        var scene = get_parent()
        if scene.has_method("playFadeOutTransition"):
            animation_playing = true
            # 临时绑定信号到当前Area2D的回调
            transition_animator.animation_finished.connect(_on_transition_animation_finished)
            scene.playFadeOutTransition()

func _on_transition_animation_finished(anim_name):
    if anim_name == "fade_out":
        var autoload = get_node("/root/Global")
        autoload.playerStartPosition = Vector2(xPosition, yPosition)
        get_tree().change_scene_to_file(room)
    # 动画结束后立即解除信号绑定
    transition_animator.animation_finished.disconnect(_on_transition_animation_finished)
    animation_playing = false

方案二:主场景统一处理场景切换

让主场景负责监听动画结束信号,Area2D只负责将目标房间和位置写入Autoload,由主场景在动画结束后执行切换,避免多脚本同时触发逻辑。

1. 修改Area2D脚本

extends Area2D

var entered = false
@export var room = ""
var animation_playing = false
@export var xPosition = 0
@export var yPosition = 0
var player

func _on_body_entered(body: PhysicsBody2D):
    entered = true
    player = body

func _on_body_exited(body):
    entered = false
    animation_playing = false

func _process(delta):
    if entered == true and animation_playing == false:
        var scene = get_parent()
        if scene.has_method("playFadeOutTransition"):
            animation_playing = true
            # 将目标信息写入Autoload
            var autoload = get_node("/root/Global")
            autoload.targetRoom = room
            autoload.playerStartPosition = Vector2(xPosition, yPosition)
            scene.playFadeOutTransition()

2. 修改主场景脚本

extends Node2D

@export var fadeIn = false

func _ready():
    $Transition/ColorRect.visible = false
    if fadeIn == true:
        $Transition/ColorRect.visible = true
        playFadeInTransition()
    # 主场景自身监听过渡动画的结束信号
    $Transition.animation_finished.connect(_on_transition_animation_finished)

func playFadeOutTransition():
    $Transition.play("fade_out")
    
func playFadeInTransition():
    $Transition.play("fade_in")

func _on_transition_animation_finished(anim_name):
    $Transition/ColorRect.visible = false
    if anim_name == "fade_out":
        var autoload = get_node("/root/Global")
        # 主场景统一执行场景切换
        get_tree().change_scene_to_file(autoload.targetRoom)

3. 补充Autoload(Global)变量

确保你的Autoload脚本中添加对应的变量:

extends Node

var playerStartPosition = Vector2.ZERO
var targetRoom = ""

内容的提问来源于stack exchange,提问作者Todu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:56:06