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();
}
}
我好像看不到什么。为什么不淡入淡出?
环境
- Manjaro 19.0.2
- Mono JIT 编译器 6.4.0(如果相关)
- 戈多 3.2
所以,问题是 AnimationPlayer
对象上的 Play
方法 kinda 像异步一样运行(不知道这是否是正确的术语)。
幸运的是,在 Godot 中有一个叫做 signals 的特性。 AnimationPlayer
对象上有 animation_started
和 animation_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 实现。而且你需要以某种方式将它集成到信号中,这看起来很麻烦。
所以,总的来说,我还是不知道怎么淡出。
前言
首先,我知道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();
}
}
我好像看不到什么。为什么不淡入淡出?
环境
- Manjaro 19.0.2
- Mono JIT 编译器 6.4.0(如果相关)
- 戈多 3.2
所以,问题是 AnimationPlayer
对象上的 Play
方法 kinda 像异步一样运行(不知道这是否是正确的术语)。
幸运的是,在 Godot 中有一个叫做 signals 的特性。 AnimationPlayer
对象上有 animation_started
和 animation_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 实现。而且你需要以某种方式将它集成到信号中,这看起来很麻烦。
所以,总的来说,我还是不知道怎么淡出。