AnimationMixer
派生: AnimationPlayer, AnimationTree
AnimationPlayer 和 AnimationTree 的基类。
描述
AnimationPlayer 和 AnimationTree 的基类,用于管理动画列表。同时还提供了用于播放和混合的常用属性和方法。
在扩展后的类中实例化播放信息数据后,就会由 AnimationMixer 负责处理混合。
教程
属性
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
方法
_post_process_key_value(animation: Animation, track: int, value: Variant, object_id: int, object_sub_idx: int) virtual const |
|
add_animation_library(name: StringName, library: AnimationLibrary) |
|
void |
|
void |
capture(name: StringName, duration: float, trans_type: TransitionType = 0, ease_type: EaseType = 0) |
void |
|
find_animation(animation: Animation) const |
|
find_animation_library(animation: Animation) const |
|
get_animation(name: StringName) const |
|
get_animation_library(name: StringName) const |
|
get_animation_library_list() const |
|
get_animation_list() const |
|
get_root_motion_position() const |
|
get_root_motion_rotation() const |
|
get_root_motion_scale() const |
|
has_animation(name: StringName) const |
|
has_animation_library(name: StringName) const |
|
void |
|
void |
rename_animation_library(name: StringName, newname: StringName) |
信号
animation_finished(anim_name: StringName) 🔗
动画播放结束时通知。
注意:如果动画正在循环播放,则不会发出此信号。
animation_libraries_updated() 🔗
当动画库发生更改时发出通知。
animation_list_changed() 🔗
当动画列表发生更改时发出通知。
animation_started(anim_name: StringName) 🔗
动画开始播放时通知。
注意:如果动画正在循环播放,则不会发出该信号。
caches_cleared() 🔗
当缓存被清除时通知,可以是自动清除,也可以是通过 clear_caches() 手动清除。
mixer_applied() 🔗
当相关的混合结果应用于目标对象时发出通知。
mixer_updated() 🔗
当处理相关属性发生更改时发出通知。
枚举
enum AnimationCallbackModeProcess: 🔗
AnimationCallbackModeProcess ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS = 0
在物理帧中处理动画(见 Node.NOTIFICATION_INTERNAL_PHYSICS_PROCESS)。尤其适用于对物理体进行动画处理。
AnimationCallbackModeProcess ANIMATION_CALLBACK_MODE_PROCESS_IDLE = 1
在处理帧中处理动画(见 Node.NOTIFICATION_INTERNAL_PROCESS)。
AnimationCallbackModeProcess ANIMATION_CALLBACK_MODE_PROCESS_MANUAL = 2
不处理动画。使用advance()手动处理动画。
enum AnimationCallbackModeMethod: 🔗
AnimationCallbackModeMethod ANIMATION_CALLBACK_MODE_METHOD_DEFERRED = 0
在动画过程中批量调用方法,然后在处理完事件后再进行调用。这样就避免了在播放过程中涉及删除节点或修改AnimationPlayer的错误。
AnimationCallbackModeMethod ANIMATION_CALLBACK_MODE_METHOD_IMMEDIATE = 1
在动画中达到时立即进行方法调用。
enum AnimationCallbackModeDiscrete: 🔗
AnimationCallbackModeDiscrete ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT = 0
将 Animation.UPDATE_CONTINUOUS 或 Animation.UPDATE_CAPTURE 轨道值与 Animation.UPDATE_DISCRETE 轨道值混合时,Animation.UPDATE_DISCRETE 轨道值优先。
AnimationCallbackModeDiscrete ANIMATION_CALLBACK_MODE_DISCRETE_RECESSIVE = 1
将 Animation.UPDATE_CONTINUOUS 或 Animation.UPDATE_CAPTURE 轨道值与 Animation.UPDATE_DISCRETE 轨道值混合时,Animation.UPDATE_CONTINUOUS 或 Animation.UPDATE_CAPTURE 轨道值优先。这是 AnimationPlayer 的默认行为。
AnimationCallbackModeDiscrete ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS = 2
始终将 Animation.UPDATE_DISCRETE 轨道的值视为 Animation.UPDATE_CONTINUOUS 和 Animation.INTERPOLATION_NEAREST。这是 AnimationTree 的默认行为。
如果值轨道上关键帧的值为无法插值的类型,则会在内部转换为 ANIMATION_CALLBACK_MODE_DISCRETE_RECESSIVE 和 Animation.UPDATE_DISCRETE。
无法插值的类型列表:
@GlobalScope.TYPE_BOOL 和 @GlobalScope.TYPE_INT 在混合时会被视为 @GlobalScope.TYPE_FLOAT,获取值时会四舍五入。
数组和向量同理,以 @GlobalScope.TYPE_PACKED_INT32_ARRAY 和 @GlobalScope.TYPE_VECTOR2I 为例,它们会被视为 @GlobalScope.TYPE_PACKED_FLOAT32_ARRAY 和 @GlobalScope.TYPE_VECTOR2。另外请注意,数组的大小也会发生插值。
@GlobalScope.TYPE_STRING 和 @GlobalScope.TYPE_STRING_NAME 的字符代码和长度会发生插值,但是关键帧的插值和混合时的插值在算法上有区别。
属性说明
如果 true 时,AnimationMixer 将执行逻辑处理。
int audio_max_polyphony = 32 🔗
每个指定的 AudioStreamPlayer 可能同时发出的声音的数量。
例如,如果该值为 32 并且动画有两个音轨,则分配的两个 AudioStreamPlayer 可以同时播放最多 32 个声音。
AnimationCallbackModeDiscrete callback_mode_discrete = 1 🔗
void set_callback_mode_discrete(value: AnimationCallbackModeDiscrete)
AnimationCallbackModeDiscrete get_callback_mode_discrete()
一般而言,可以将轨道设置为 Animation.UPDATE_DISCRETE 降低更新频率,通常在最近邻插值时使用。
但在使用 Animation.UPDATE_CONTINUOUS 进行混合时需要考虑不同的结果,可以用 callback_mode_discrete 来显式指定。另见 AnimationCallbackModeDiscrete。
为了在混合时得到更好的结果,建议将其设置为 ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS,在混合时每一帧都更新。其他值主要用于兼容,在不需要混合时没有问题,但需要混合时则可能产生问题。
AnimationCallbackModeMethod callback_mode_method = 0 🔗
void set_callback_mode_method(value: AnimationCallbackModeMethod)
AnimationCallbackModeMethod get_callback_mode_method()
用于“方法调用”轨道的调用模式。
AnimationCallbackModeProcess callback_mode_process = 1 🔗
void set_callback_mode_process(value: AnimationCallbackModeProcess)
AnimationCallbackModeProcess get_callback_mode_process()
更新动画的过程通知。
如果为 true,则混合使用确定性算法。总权重不进行归一化,在初始值的基础上进行累加(初始值为 0,表示可能存在的 "RESET" 动画)。
这意味着如果混合总权重为 0.0,则结果等于 "RESET" 动画。
如果混合动画之间的轨道数量不同,则缺少轨道的动画将被视为具有初始值。
如果为 false,则混合不会使用确定性算法。总权重将归一化且始终为 1.0。如果混合动画之间的轨道数量不同,则不会对缺少轨道的动画执行任何操作。
注意:在 AnimationTree 中,与 AnimationNodeAdd2 、 AnimationNodeAdd3 、 AnimationNodeSub2 或权重大于 1.0 混合可能产生意想不到的结果。
例如,如果 AnimationNodeAdd2 混合了两个取值为 1.0 的节点,则总权重为 2.0,但它将被归一化使总权重保持 1.0,且结果将等于取值为 0.5 的 AnimationNodeBlend2。
由编辑器使用。如果设置为 true,场景将被保存,并应用重置动画(带有键 "RESET" 的动画)的效果,就好像它已被定位到时间 0 一样,编辑器保留场景在保存之前的值。
这使得在编辑器中预览和编辑动画更加方便,因为对场景的更改,只要在重置动画中被设置,就不会被保存。
bool root_motion_local = false 🔗
如果为 true,则混合前会将 get_root_motion_position() 的值当作局部平移值提取。换句话说,会被当作在旋转后再进行平移。
NodePath root_motion_track = NodePath("") 🔗
用于根部运动的动画轨道的路径。路径必须是指向某一节点的有效场景树路径,必须从将实现动画的节点的父节点开始指定。root_motion_track 使用与 Animation.track_set_path() 相同的格式,但注意必须指定一个骨骼。
如果轨道的类型是 Animation.TYPE_POSITION_3D、Animation.TYPE_ROTATION_3D、或者 Animation.TYPE_SCALE_3D,那么将取消视觉上的变换,其动画看起来将是留在原地。另见 get_root_motion_position()、get_root_motion_rotation()、get_root_motion_scale()、RootMotionView。
NodePath root_node = NodePath("..") 🔗
节点路径引用将从其出发的节点。
方法说明
Variant _post_process_key_value(animation: Animation, track: int, value: Variant, object_id: int, object_sub_idx: int) virtual const 🔗
虚函数,用于播放期间在获取关键帧之后的处理。
Error add_animation_library(name: StringName, library: AnimationLibrary) 🔗
将动画库 library 添加至动画播放器中,键名为 name。
AnimationMixer 默认拥有一个全局库,键名为空字符串。要向这个全局库中添加动画:
var global_library = mixer.get_animation_library("")
global_library.add_animation("animation_name", animation_resource)
手动将动画前进指定的时间(单位为秒)。
void capture(name: StringName, duration: float, trans_type: TransitionType = 0, ease_type: EaseType = 0) 🔗
如果 name 指定的动画轨道具有 Animation.UPDATE_CAPTURE 选项,则会将轨道路径表示的对象当前值存储下来作为缓存。如果已存在捕获缓存,则会丢弃旧缓存。
在此之后,就会在播放过程中进行时长为 duration 的与当前动画混合结果的插值,类似淡入淡出。
可以使用 trans_type 来指定插值曲线。为了达到最佳效果,如果轨道的第一个关键帧非零或键值不会改变,则最好使用 Tween.TRANS_LINEAR;如果键值有线性变化,则最好使用 Tween.TRANS_QUAD。
void clear_caches() 🔗
AnimationMixer 会缓存动画节点。如果一个节点消失,它可能不会注意到;clear_caches() 能够强制它再次更新缓存。
StringName find_animation(animation: Animation) const 🔗
返回 animation 的键;如果未找到,则返回一个空的 StringName。
StringName find_animation_library(animation: Animation) const 🔗
返回包含 animation 的 AnimationLibrary 的键;如果找不到,则返回一个空的 StringName。
Animation get_animation(name: StringName) const 🔗
返回带有键 name 的 Animation。如果动画不存在,则返回 null 并记录错误。
AnimationLibrary get_animation_library(name: StringName) const 🔗
返回第一个键为 name 的 AnimationLibrary,如果没有找到则返回 null。
要获得 AnimationMixer 的全局动画库,请使用 get_animation_library("")。
Array[StringName] get_animation_library_list() const 🔗
返回存储库的键名列表。
PackedStringArray get_animation_list() const 🔗
返回存储的动画键列表。
Vector3 get_root_motion_position() const 🔗
获取 root_motion_track 的位置运动增量,这是一个可以在其他地方使用的 Vector3。
如果 root_motion_track 所指向的轨道不是 Animation.TYPE_POSITION_3D 类型,则返回 Vector3(0, 0, 0)。
另见 root_motion_track 和 RootMotionView。
最基础的示例就是将位置应用到 CharacterBody3D 上:
var current_rotation
func _process(delta):
if Input.is_action_just_pressed("animate"):
current_rotation = get_quaternion()
state_machine.travel("Animate")
var velocity = current_rotation * animation_tree.get_root_motion_position() / delta
set_velocity(velocity)
move_and_slide()
与 get_root_motion_rotation_accumulator() 配合使用就可以将节点的旋转考虑进来,让应用的根运动位置更为准确。
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation())
var velocity = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta
set_velocity(velocity)
move_and_slide()
如果 root_motion_local 为 true,则会返回预先与逆向旋转相乘后的平移值。
此时可以这样编写代码:
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation())
var velocity = get_quaternion() * animation_tree.get_root_motion_position() / delta
set_velocity(velocity)
move_and_slide()
Vector3 get_root_motion_position_accumulator() const 🔗
检索具有 root_motion_track 的位置轨道的混合值,返回的是可以在其他地方使用的 Vector3。
在想要遵循动画的初始动画帧值的情况下很有用。
例如,如果前一帧播放的是一个只有单个动画帧 Vector3(0, 0, 0) 的动画,然后下一帧播放的是一个只有单个动画帧Vector3(1, 0, 1) 的动画,它们之间的差异可以这样计算:
var prev_root_motion_position_accumulator
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
var current_root_motion_position_accumulator = animation_tree.get_root_motion_position_accumulator()
var difference = current_root_motion_position_accumulator - prev_root_motion_position_accumulator
prev_root_motion_position_accumulator = current_root_motion_position_accumulator
transform.origin += difference
不过,如果动画是循环播放的,就可能会发生预料之外的不连续变化,所以这只对一些简单的情况有用。
Quaternion get_root_motion_rotation() const 🔗
检索带有 root_motion_track 的旋转运动,作为一个 Quaternion,可以在其他地方使用。
如果 root_motion_track 不是 Animation.TYPE_ROTATION_3D 类型的轨迹的路径,返回 Quaternion(0, 0, 0, 1) 。
另见 root_motion_track 和 RootMotionView。
最基本的例子是对 CharacterBody3D 应用旋转。
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation() )
Quaternion get_root_motion_rotation_accumulator() const 🔗
检索带有 root_motion_track 的旋转轨道的混合值,作为一个 Quaternion,可以在其他地方使用。
这里必须正确地结合根运动位置,并且要考虑到旋转。参考 get_root_motion_position()。
并且,当你想重视动画的初始动画帧的值时,这会很有用。
比如说,如果一个动画在上一帧只播放一个 Quaternion(0, 0, 0, 1) 动画帧,并且一个动画在下一帧只播放了一个动画帧的 Quaternion(0, 0.707, 0, 0.707) 时,它们相差的值可以这样求出:
var prev_root_motion_rotation_accumulator
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
var current_root_motion_rotation_accumulator = animation_tree.get_root_motion_rotation_accumulator()
var difference = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator
prev_root_motion_rotation_accumulator = current_root_motion_rotation_accumulator
transform.basis *= Basis(difference)
然而,当一个动画循环时,可能会得到一个意料之外的变化,所以这个只在一些简单情况下才有用。
Vector3 get_root_motion_scale() const 🔗
获取 root_motion_track 的缩放运动增量,类型为 Vector3,可以在其他地方使用。
如果 root_motion_track 不是类型为 Animation.TYPE_SCALE_3D 的轨道的路径,则返回 Vector3(0, 0, 0) 。
另见 root_motion_track 和 RootMotionView。
最基本的例子是对 CharacterBody3D 应用缩放。
var current_scale = Vector3(1, 1, 1)
var scale_accum = Vector3(1, 1, 1)
func _process(delta):
if Input.is_action_just_pressed("animate"):
current_scale = get_scale()
scale_accum = Vector3(1, 1, 1)
state_machine.travel("Animate")
scale_accum += animation_tree.get_root_motion_scale()
set_scale(current_scale * scale_accum)
Vector3 get_root_motion_scale_accumulator() const 🔗
检索带有 root_motion_track 的缩放轨道的混合值,作为一个 Vector3,可以在其他地方使用。
例如,如果一个动画在前一帧只播放了一个动画帧 Vector3(1, 1, 1),并且一个动画在后一帧只播放了一个动画帧 Vector3(2, 2, 2),他们之间相差的值可以这样求出:
var prev_root_motion_scale_accumulator
func _process(delta):
if Input.is_action_just_pressed("animate"):
state_machine.travel("Animate")
var current_root_motion_scale_accumulator = animation_tree.get_root_motion_scale_accumulator()
var difference = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator
prev_root_motion_scale_accumulator = current_root_motion_scale_accumulator
transform.basis = transform.basis.scaled(difference)
然而,当一个动画循环时,可能会得到一个意料之外的变化,所以这个只在一些简单情况下才有用。
bool has_animation(name: StringName) const 🔗
如果该 AnimationMixer 存有键名为 name 的 Animation,则返回 true。
bool has_animation_library(name: StringName) const 🔗
如果该 AnimationMixer 存有键名为 name 的 AnimationLibrary,则返回 true。
void remove_animation_library(name: StringName) 🔗
移除与键 name 关联的 AnimationLibrary。
void rename_animation_library(name: StringName, newname: StringName) 🔗
将与键 name 关联的 AnimationLibrary 移动到键 newname。