畫總在打滑?Godot 根運(yùn)動(dòng)從零到調(diào)優(yōu))
為什么角色動(dòng)畫總在打滑Godot 根運(yùn)動(dòng)從零到調(diào)優(yōu)【免費(fèi)下載鏈接】godotGodot Engine – Multi-platform 2D and 3D game engine項(xiàng)目地址: https://gitcode.com/GitHub_Trending/go/godot你在測(cè)試場(chǎng)景里盯著角色看久了總能發(fā)現(xiàn)那點(diǎn)不對(duì)勁腳掌落地了身體卻還在往前漂跑動(dòng)中穿墻而過或者下臺(tái)階時(shí)整個(gè)人懸了半拍。說白了動(dòng)畫在演物理在猜兩邊對(duì)不上賬觀感就像給角色貼了張會(huì)滑行的貼圖。在 Godot 里治這個(gè)問題的標(biāo)準(zhǔn)藥方就是 Godot 根運(yùn)動(dòng)Root Motion 動(dòng)畫——把動(dòng)畫里的位移真正交給物理系統(tǒng)去執(zhí)行。先分清位移到底是畫的還是走的一句話回答它解決什么讓動(dòng)畫自己產(chǎn)生位移而不是代碼在旁白里喊你往左挪 0.3 米。傳統(tǒng)做法是給節(jié)點(diǎn)掛 Transform 軌道動(dòng)畫每幀改寫 position 和 rotation。這相當(dāng)于皮影戲——影子在動(dòng)線軸沒動(dòng)。物理系統(tǒng)看到的只是一具被強(qiáng)行挪位置的模型碰撞體跟著瞬移所以你會(huì)穿墻、會(huì)懸空、循環(huán)點(diǎn)還會(huì)跳變。根運(yùn)動(dòng)換了個(gè)思路動(dòng)畫師把腳步畫在根骨骼一般是 Hips 那一層的位移曲線上引擎每幀從這條曲線里結(jié)賬出一筆位移預(yù)算再塞給物理求解器。于是每一步都有碰撞檢測(cè)兜底動(dòng)畫和物理天然同頻。維度Transform 軌道直改根運(yùn)動(dòng)位移從哪來代碼寫 position或軌道硬改根骨骼的位移曲線折算物理系統(tǒng)看到什么一具瞬移的模型一次帶碰撞檢測(cè)的移動(dòng)循環(huán)接縫位置不重合就跳變位移按幀結(jié)算接縫平滑適用對(duì)象UI 擺動(dòng)、簡(jiǎn)單循環(huán)走跑跳等角色位移動(dòng)手從導(dǎo)入到物理接管三步走完第一步導(dǎo)入模型時(shí)就把動(dòng)畫勾上把 glTF/FBX 拖進(jìn)項(xiàng)目導(dǎo)入設(shè)置里確認(rèn)Import Animation已勾選。很多人漏的就是這一步結(jié)果導(dǎo)入完發(fā)現(xiàn)動(dòng)畫列表是空的回頭重導(dǎo)半天。第二步給根骨骼定位再確認(rèn)烘焙開關(guān)在檢查器里找到動(dòng)畫的根運(yùn)動(dòng)Root Motion相關(guān)選項(xiàng)把根骨骼指到角色的根骨上——通常是root或者Hips。指哪根骨哪根骨的位移就被當(dāng)作整只角色的位移所以別指到脊椎中段那會(huì)讓角色從腰上飛。順手在腳本里聲明一下這條開關(guān)后面統(tǒng)一走物理采樣$AnimationPlayer.root_motion_track root_position # 指定根運(yùn)動(dòng)位移軌道 $AnimationPlayer.process_callback ANIMATION_PROCESS_PHYSICS # 改在物理幀采樣避免和幀率漂移第三步讓 CharacterBody 接住這筆位移這是整篇最關(guān)鍵的一步。別再在動(dòng)畫里直接改 position 了把每幀的位移預(yù)算從動(dòng)畫播放器里取出來喂給move_and_slide讓它替你完成碰撞檢測(cè)和重力func _physics_process(_delta): var motion : $AnimationPlayer.get_root_motion_delta() # 本幀根運(yùn)動(dòng)產(chǎn)生的位移 if motion ! Vector3.ZERO: velocity motion # 疊加進(jìn)速度交給物理系統(tǒng)結(jié)算 move_and_slide() # 一次調(diào)用搞定碰撞與滑動(dòng)跑起來之后你會(huì)明顯感覺到區(qū)別腳步不再飄著走下臺(tái)階那半拍懸空也沒了。進(jìn)階用 AnimationTree 狀態(tài)機(jī)管住切換走、跑、待機(jī)多段動(dòng)畫切換時(shí)裸寫 AnimationPlayer 的交叉淡化很快就亂。上 AnimationTree拖一個(gè)狀態(tài)機(jī)節(jié)點(diǎn)每個(gè)狀態(tài)掛一段動(dòng)畫再用 BlendSpace 把同方向的走/跑動(dòng)畫排進(jìn)一個(gè)混合空間用速度值驅(qū)動(dòng)過渡權(quán)重。一個(gè)最小能跑的例子——切到跑步狀態(tài)并繼續(xù)接住根運(yùn)動(dòng)位移var playback : $AnimationTree.get(parameters/playback) # 拿到播放控制器 playback.travel(run) # 狀態(tài)機(jī)切到跑步狀態(tài) var motion : $AnimationTree.get_root_motion_delta() # 混合后的根運(yùn)動(dòng)位移 move_and_slide(motion) # 物理接管碰撞與滑動(dòng)一次處理要點(diǎn)就一條無(wú)論動(dòng)畫從哪個(gè)狀態(tài)、以什么權(quán)重混合出來位移結(jié)算永遠(yuǎn)只在物理回調(diào)里做一遍別在動(dòng)畫回調(diào)里再補(bǔ)一次。排坑卡三種最常見的不對(duì)勁癥狀定位三行內(nèi)修復(fù)循環(huán)處腳底打滑對(duì)比循環(huán)首尾兩幀根骨骼位置是否一致首尾幀根骨骼局部位置對(duì)齊差值會(huì)被當(dāng)成本幀位移穿墻 / 貼墻穿透看膠囊碰撞體相對(duì)模型的比例把膠囊半徑調(diào)到模型半徑的 1.2 倍左右并加大碰撞步進(jìn)動(dòng)畫多的時(shí)候掉幀用 PerformanceMonitor 看動(dòng)畫更新耗時(shí)開啟有損壓縮ANIMATION_COMPRESSION_LOSSY減少軌道采樣精度補(bǔ)充兩句滑步多半是動(dòng)畫源的問題別在代碼里硬補(bǔ)穿透多半是碰撞體太瘦不是根運(yùn)動(dòng)沒生效。收尾到這里可以下個(gè)結(jié)論了根運(yùn)動(dòng)不是可選的錦上添花而是現(xiàn)代角色動(dòng)畫的默認(rèn)選項(xiàng)。位移由動(dòng)畫產(chǎn)生、由物理結(jié)算這條鏈路一旦跑通走跑切換、攻擊前沖、受擊后退都能復(fù)用同一套邏輯手感自然就上來了。想繼續(xù)深挖順著這三處看就夠引擎源碼動(dòng)畫混合與根運(yùn)動(dòng)的實(shí)現(xiàn)都在scene/animation/目錄類參考doc/classes/AnimationTree.xml、doc/classes/AnimationPlayer.xml官方入門2D Sprite Animation 教程Asset Library 可搜【免費(fèi)下載鏈接】godotGodot Engine – Multi-platform 2D and 3D game engine項(xiàng)目地址: https://gitcode.com/GitHub_Trending/go/godot創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考