(Godot 引擎)将 AnimationPlayer 键值设置为当前值
(Godot Engine) Setting AnimationPlayer key values to current values
如何将动画的键值设置为动画中引用的对象的当前值,类似于将 null 传递给 initial_val 和/或 final_val 补间节点的参数?
"Setting the initial value to null uses the current value of the property." Tween Node Documentation
我的答案是我目前尝试过的方法,但我担心它太复杂了。
使用此方法,我可以将现有动画的关键值设置到指定的轨道位置 _animation_position,并使用参数 [ 中指定的节点的当前值=13=]_node_names 并且可选地,该节点的特定 属性 传入 _property_names,否则,所有属性都存在在动画中与节点相关的内容将被更改。
func Animation_Set_Current_Values(_animation_player: AnimationPlayer, _animation_name: String = "", _animation_position: int = 0,
_node_names: Array = [], _property_names: Array = [], _disable_unwanted: bool = true, _play_animation: bool = true) -> void:
if not _node_names.empty():
if not _animation_player.get_animation_list().empty():
# Use the first animation in the animation player if no animation name is specified for convenience
var _detected_animation_name: String = _animation_name if (
not _animation_name.empty() and _animation_player.has_animation(_animation_name)) else _animation_player.get_animation_list()[0]
var _animation: Animation = _animation_player.get_animation(_detected_animation_name)
# Store detected track / node information: Node_Name: [{_property: _track_count}, ...]
var _track_data: Dictionary = {}
if _animation.get_track_count() != 0:
for _track in _animation.get_track_count():
var _track_path: NodePath = _animation.track_get_path(_track)
var _node_path: String = (_track_path as String).split(":")[0]
var _node_property: String = (_track_path as String).split(":")[1]
var _node: Object = _animation_player.get_parent().get_node(_node_path)
if _node != null:
if not _track_data.has(_node): _track_data[_node] = []
_track_data[_node].append({_node_property: _track})
if _disable_unwanted: _animation.track_set_enabled(_track, false)
# Set track keys values to the current initial values
if not _track_data.empty():
for _track_data_node in _track_data.keys():
if _node_names.has(_track_data_node.name):
for _track_data_property in _track_data[_track_data_node]:
var _track_data_property_name: String = _track_data_property.keys().front()
var _track_data_property_track_idx: int = _track_data_property.values().front()
var _node_property = _track_data_node.get(_track_data_property_name)
if _node_property != null:
if _property_names.has(_track_data_property_name) or _property_names.empty():
if _animation_position <= _animation.track_get_key_count(_track_data_property_track_idx) - 1:
_animation.track_set_key_value(_track_data_property_track_idx, _animation_position, _node_property)
_animation.track_set_enabled(_track_data_property_track_idx, true)
# Optionally, play the animation if specified
if _play_animation: _animation_player.play(_detected_animation_name)
properly transitioning two animations in the following scenario: considering an character swinging a sword, there are two animations: "swing" and "parry", if I play the "parry" animation while the "swing" animation is still in process
你有两个动画,你想在它们之间混合。 这不是你问的(XY problem)。
使用AnimationPlayer
,您可以指定任意两个动画之间的过渡时间。 包括一个动画和它本身,当你告诉 Godot 在播放同一个动画时播放一个动画时就会发生这种情况。
在动画面板(编辑器底部)中,第一个动画 selected(在您的示例中为“摇摆”),单击“动画”按钮并 select “编辑过渡”。它将打开该 selected 动画的“跨动画混合时间”对话框。
对话框将显示所有带有编号的动画,默认为 0。这是 Godot 混合动画的时间,以秒为单位。
0(默认值)表示瞬时。也就是说,如果您播放另一个动画(在您的示例中为“parry”),它将捕捉到该动画的起始值……这不是您想要的。而是增加时间。
注意 Godot 不会插值到新动画的起始值,它会插值到新动画播放的当前值。
重申一下这个场景,当播放第一个动画(比如“挥舞”)时,你播放第二个动画(比如“招架”)。
播放第二个动画,但设置的值将不是动画中的值。相反,它们将是当前值和动画中的值之间的一些插值。插值将使得在开始时当前值保持不变,并且在您在“交叉动画混合时间”对话框中配置的任何时间之后,该值就是动画中的值。
是的,这是线性插值。 至少据我所知,请记住我们很少希望过渡很长。
如果用当前值替换动画的初始值,则动画会在第二个关键帧处满足动画的值。
您可以改为让过渡时间与第二个关键帧匹配。 不完全相同,因为您可以在不同时间拥有不对齐的关键帧轨道,并且您可以控制每个轨道的插值方式。然而,我在这里介绍的方法工作要少得多(根本没有代码)。
如果你不想线性插值,或者你想在两个以上的动画之间插值,请使用AnimationTree. See also Controlling animation states。
如何将动画的键值设置为动画中引用的对象的当前值,类似于将 null 传递给 initial_val 和/或 final_val 补间节点的参数?
"Setting the initial value to null uses the current value of the property." Tween Node Documentation
我的答案是我目前尝试过的方法,但我担心它太复杂了。
使用此方法,我可以将现有动画的关键值设置到指定的轨道位置 _animation_position,并使用参数 [ 中指定的节点的当前值=13=]_node_names 并且可选地,该节点的特定 属性 传入 _property_names,否则,所有属性都存在在动画中与节点相关的内容将被更改。
func Animation_Set_Current_Values(_animation_player: AnimationPlayer, _animation_name: String = "", _animation_position: int = 0,
_node_names: Array = [], _property_names: Array = [], _disable_unwanted: bool = true, _play_animation: bool = true) -> void:
if not _node_names.empty():
if not _animation_player.get_animation_list().empty():
# Use the first animation in the animation player if no animation name is specified for convenience
var _detected_animation_name: String = _animation_name if (
not _animation_name.empty() and _animation_player.has_animation(_animation_name)) else _animation_player.get_animation_list()[0]
var _animation: Animation = _animation_player.get_animation(_detected_animation_name)
# Store detected track / node information: Node_Name: [{_property: _track_count}, ...]
var _track_data: Dictionary = {}
if _animation.get_track_count() != 0:
for _track in _animation.get_track_count():
var _track_path: NodePath = _animation.track_get_path(_track)
var _node_path: String = (_track_path as String).split(":")[0]
var _node_property: String = (_track_path as String).split(":")[1]
var _node: Object = _animation_player.get_parent().get_node(_node_path)
if _node != null:
if not _track_data.has(_node): _track_data[_node] = []
_track_data[_node].append({_node_property: _track})
if _disable_unwanted: _animation.track_set_enabled(_track, false)
# Set track keys values to the current initial values
if not _track_data.empty():
for _track_data_node in _track_data.keys():
if _node_names.has(_track_data_node.name):
for _track_data_property in _track_data[_track_data_node]:
var _track_data_property_name: String = _track_data_property.keys().front()
var _track_data_property_track_idx: int = _track_data_property.values().front()
var _node_property = _track_data_node.get(_track_data_property_name)
if _node_property != null:
if _property_names.has(_track_data_property_name) or _property_names.empty():
if _animation_position <= _animation.track_get_key_count(_track_data_property_track_idx) - 1:
_animation.track_set_key_value(_track_data_property_track_idx, _animation_position, _node_property)
_animation.track_set_enabled(_track_data_property_track_idx, true)
# Optionally, play the animation if specified
if _play_animation: _animation_player.play(_detected_animation_name)
properly transitioning two animations in the following scenario: considering an character swinging a sword, there are two animations: "swing" and "parry", if I play the "parry" animation while the "swing" animation is still in process
你有两个动画,你想在它们之间混合。 这不是你问的(XY problem)。
使用AnimationPlayer
,您可以指定任意两个动画之间的过渡时间。 包括一个动画和它本身,当你告诉 Godot 在播放同一个动画时播放一个动画时就会发生这种情况。
在动画面板(编辑器底部)中,第一个动画 selected(在您的示例中为“摇摆”),单击“动画”按钮并 select “编辑过渡”。它将打开该 selected 动画的“跨动画混合时间”对话框。
对话框将显示所有带有编号的动画,默认为 0。这是 Godot 混合动画的时间,以秒为单位。
0(默认值)表示瞬时。也就是说,如果您播放另一个动画(在您的示例中为“parry”),它将捕捉到该动画的起始值……这不是您想要的。而是增加时间。
注意 Godot 不会插值到新动画的起始值,它会插值到新动画播放的当前值。
重申一下这个场景,当播放第一个动画(比如“挥舞”)时,你播放第二个动画(比如“招架”)。
播放第二个动画,但设置的值将不是动画中的值。相反,它们将是当前值和动画中的值之间的一些插值。插值将使得在开始时当前值保持不变,并且在您在“交叉动画混合时间”对话框中配置的任何时间之后,该值就是动画中的值。
是的,这是线性插值。 至少据我所知,请记住我们很少希望过渡很长。
如果用当前值替换动画的初始值,则动画会在第二个关键帧处满足动画的值。
您可以改为让过渡时间与第二个关键帧匹配。 不完全相同,因为您可以在不同时间拥有不对齐的关键帧轨道,并且您可以控制每个轨道的插值方式。然而,我在这里介绍的方法工作要少得多(根本没有代码)。
如果你不想线性插值,或者你想在两个以上的动画之间插值,请使用AnimationTree. See also Controlling animation states。