(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