AnimationPlayer 动画不在 Godot 中播放

AnimationPlayer animations do not play in Godot

前言

首先,我知道post在这个平台上不鼓励为代码使用图形资源。我也会 post 代码,但在这种特殊情况下,我认为 post 播放有关它的视频比 post 播放一些任意代码更有帮助,因为游戏项目的结构真的取决于他们的要求。但是,我仍然尊重平台的规则,所以如果 mod 要求我根据社区规则格式化我的问题,我可以这样做,或者他们也可以简单地删除我的问题。我尊重这一点。

问题

这实际上是一个简单的问题,但因为它的简单性而让我抓狂。我只想在加载场景时淡入,然后在单击按钮时淡出。至于我是怎么做到的,this is the video about it.

总而言之,我加载了另一个名为 "Fader" 的场景,其中包含黑色的 ColorRect 和用于更改 ColorRect 的 alpha 值的 AnimationPlayer

代码如下,相关部分有额外注释:

using Godot;
using System;

public class TitleScreen : Control
{
    private Button[] buttons;
    private Control fader;  // the scene that I inject

    public override void _Ready()  // when title screen gets ready
    {
        GD.Print("Preparing TitleScreen...");
        InitButtons();
        InitFader();  // initialize fader
        FadeIn();  // do fade in animation
    }

    private void InitFader()  // initializing fader
    {
        GD.Print("Initializing fader...");
        var faderScene = (PackedScene)ResourceLoader.Load("res://components/Fader.tscn");  // load external fader scene
        fader = (Control)faderScene.Instance();  // instantiate the scene
        fader.SetSize(OS.WindowSize);  // set the size of fader scene to the game window, just in case
        var rect = (ColorRect)fader.GetNode("rect");  // get "rect" child from fader scene
        rect.SetSize(OS.WindowSize);  // set "rect" size to the game window as well, just in case
        fader.Visible = false;  // set the visibility to false
        AddChild(fader);  // add initialized fader scene as a child of title screen
    }

    private void InitButtons()
    {
        GD.Print("Initializing buttons...");
        buttons = new Button[3]{
            (Button)GetNode("menu_container/leftmenu_container/menu/start_button"),
            (Button)GetNode("menu_container/leftmenu_container/menu/continue_button"),
            (Button)GetNode("menu_container/leftmenu_container/menu/exit_button"),
        };

        GD.Print("Adding events to buttons...");
        buttons[0].Connect("pressed", this, "_StartGame");
        buttons[2].Connect("pressed", this, "_QuitGame");
    }

    private void FadeIn()
    {
        GD.Print("Fading in...");
        fader.Visible = true;  // set visibility of fader to true
        var player = (AnimationPlayer)fader.GetNode("player");  // get animation player
        player.Play("FadeIn");  // play FadeIn animation
        fader.Visible = false;  // set visibility of fader to false
    }

    private void FadeOut()
    {
        // similar to FadeIn
        GD.Print("Fading out...");
        fader.Visible = true;
        var player = (AnimationPlayer)fader.GetNode("player");
        player.Play("FadeOut");
        fader.Visible = false;
    }

    public void _StartGame()  // whenever I click start game button
    {
        FadeOut();  // fade out
        GetTree().ChangeScene("res://stages/Demo01.tscn");
    }

    public void _QuitGame()  // whenever I click quit game button
    {
        FadeOut();  // fade out
        GetTree().Quit();
    }
}

我好像看不到什么。为什么不淡入淡出?


环境

所以,问题是 AnimationPlayer 对象上的 Play 方法 kinda 像异步一样运行(不知道这是否是正确的术语)。

幸运的是,在 Godot 中有一个叫做 signals 的特性。 AnimationPlayer 对象上有 animation_startedanimation_finished 信号。基本上,我为 Fader 场景创建了一个 C# 脚本,将信号从 player 连接到 fader,如:

  • animation_started_FaderAnimationStart
  • animation_finished_FaderAnimationEnd

最后,我的脚本如下所示:

using Godot;
using System;

public class Fader : Control
{
    private ColorRect rect;
    private AnimationPlayer player;

    public override void _Ready()
    {
        GD.Print("Initializing Fader...");

        rect = (ColorRect)GetNode("rect");
        player = (AnimationPlayer)GetNode("player");

        SetSize(OS.WindowSize);
        rect.SetSize(OS.WindowSize);

        Visible = false;
    }

    private void _FaderAnimationStart(String anim_name)
    {
        Visible = true;
    }

    private void _FaderAnimationEnd(String anim_name)
    {
        Visible = false;
    }
}

感谢 njamster's answer and Hans Passant's 我解决了它。

然而,这只解决了一半的问题。是的,场景现在在加载时淡入但不会淡出。鉴于它执行有点异步(同样,我不确定这是否是正确的术语),在 运行 动画时更改场景中断。 当我解决了那个问题后我会更新答案。

更新

好吧,我似乎无法解决淡出部分,因为它需要从初始化的子场景访问父节点。我能想到一些方法。

第一个是以某种方式参数化"Fader"场景。这可以通过多种方式完成,但最后,当您从另一个场景初始化它时,您需要将其转换为 Fader,我不知道这是否是一种有效的方法。另一个问题是在代码库中对此进行标准化。 here.

中讨论了类似的方法

第二个是 write it as a plugin,它有优点也有缺点。 C# 在这个特定领域并没有真正经过实战测试。

第三个是使用状态管理系统。这是 Godot 的 redux 实现。而且你需要以某种方式将它集成到信号中,这看起来很麻烦。

所以,总的来说,我还是不知道怎么淡出。