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) 🔗
Notifies when an animation starts playing.
Note: This signal is not emitted if an animation is looping.
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 時,前兩者具有優先權。這是 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,結果等同 AnimationNodeBlend2 權重為 0.5。
此功能由編輯器使用。若設為 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。