間軸實(shí)現(xiàn)物體旋轉(zhuǎn)與移動(dòng)動(dòng)畫)
1. 項(xiàng)目概述為什么Timeline是UE5新手的第一個(gè)動(dòng)畫利器如果你剛接觸虛幻引擎5面對(duì)琳瑯滿目的動(dòng)畫系統(tǒng)——?jiǎng)赢嬎{(lán)圖、狀態(tài)機(jī)、Sequencer——可能會(huì)感到無從下手。別急今天我要分享的這個(gè)工具絕對(duì)是讓你快速獲得成就感、理解UE動(dòng)畫邏輯的絕佳起點(diǎn)Timeline時(shí)間軸。這個(gè)項(xiàng)目標(biāo)題“用Timeline輕松實(shí)現(xiàn)物體旋轉(zhuǎn)與移動(dòng)動(dòng)畫”聽起來簡(jiǎn)單但它背后蘊(yùn)含的是UE中“基于時(shí)間的數(shù)值驅(qū)動(dòng)”這一核心動(dòng)畫思想。無論是讓一個(gè)寶箱緩緩打開讓一盞燈周期性閃爍還是讓一個(gè)平臺(tái)在兩點(diǎn)間來回移動(dòng)Timeline都能以最直觀、最藍(lán)圖化的方式幫你搞定。很多新手會(huì)誤以為只有復(fù)雜的骨骼動(dòng)畫才叫動(dòng)畫。其實(shí)任何物體屬性位置、旋轉(zhuǎn)、縮放、顏色、亮度甚至一個(gè)浮點(diǎn)數(shù)隨時(shí)間的變化都是動(dòng)畫。Timeline正是處理這類“屬性動(dòng)畫”的瑞士軍刀。相較于直接寫代碼或用SequencerTimeline集成在藍(lán)圖內(nèi)部可視化程度極高所見即所得調(diào)試極其方便。通過這個(gè)項(xiàng)目你不僅能學(xué)會(huì)讓物體動(dòng)起來更能深刻理解曲線Curve驅(qū)動(dòng)和事件調(diào)度這兩個(gè)在UE開發(fā)中無處不在的概念。這為你后續(xù)學(xué)習(xí)更高級(jí)的材質(zhì)動(dòng)畫比如控制“ue5 半透明材質(zhì)”的透明度、序列器Sequencer剪輯甚至是簡(jiǎn)單的游戲邏輯如“ue5 倒計(jì)時(shí)材質(zhì)”的實(shí)現(xiàn)基礎(chǔ)都打下了堅(jiān)實(shí)的基礎(chǔ)。2. 核心思路拆解Timeline如何驅(qū)動(dòng)世界在動(dòng)手連接節(jié)點(diǎn)之前我們必須先搞懂Timeline的工作原理。你可以把它想象成一個(gè)高級(jí)的、圖形化的計(jì)時(shí)器但它比簡(jiǎn)單的Delay節(jié)點(diǎn)強(qiáng)大得多。2.1 Timeline的三大核心引腳一個(gè)Timeline節(jié)點(diǎn)通常有三個(gè)關(guān)鍵的執(zhí)行引腳Exec Pin它們控制著動(dòng)畫的播放行為Play從當(dāng)前時(shí)間開始正向播放。如果已經(jīng)在播放則無效果。這是最常用的啟動(dòng)方式。Play from Start無論當(dāng)前時(shí)間在哪都跳回時(shí)間軸起點(diǎn)通常是0開始正向播放。適用于需要嚴(yán)格從頭開始的動(dòng)畫。Stop停止播放并輸出當(dāng)前的時(shí)間點(diǎn)。停止后物體的狀態(tài)會(huì)停留在最后一幀。Reverse反向播放。Reverse from End從時(shí)間軸終點(diǎn)開始反向播放。理解這些引腳的區(qū)別至關(guān)重要。例如讓一扇門打開后自動(dòng)關(guān)閉流程可能是玩家交互 →Play from Start開門動(dòng)畫→ 動(dòng)畫結(jié)束事件 → Delay 2秒 →Reverse關(guān)門動(dòng)畫。2.2 輸出類型FloatVectorEvent這是Timeline的精髓所在它有三種數(shù)據(jù)輸出方式Float軌道輸出一個(gè)隨時(shí)間變化的浮點(diǎn)數(shù)。這是我們實(shí)現(xiàn)旋轉(zhuǎn)控制旋轉(zhuǎn)角度和勻速移動(dòng)控制插值A(chǔ)lpha值的關(guān)鍵。你可以通過編輯曲線讓這個(gè)數(shù)值如何變化線性、先快后慢、彈性抖動(dòng)等。Vector軌道輸出一個(gè)隨時(shí)間變化的向量X, Y, Z。非常適合直接驅(qū)動(dòng)物體的位置Location或縮放Scale。例如讓物體從A點(diǎn)移動(dòng)到B點(diǎn)你可以創(chuàng)建一個(gè)Vector軌道在0秒時(shí)鍵值設(shè)為A點(diǎn)坐標(biāo)在2秒時(shí)鍵值設(shè)為B點(diǎn)坐標(biāo)。Event軌道在時(shí)間軸的特定時(shí)刻觸發(fā)一個(gè)自定義事件。比如在動(dòng)畫播放到第1.5秒時(shí)播放一個(gè)音效或者在動(dòng)畫結(jié)束時(shí)觸發(fā)下一個(gè)邏輯。對(duì)于本次的“旋轉(zhuǎn)與移動(dòng)”項(xiàng)目我們將主要使用Float軌道來控制旋轉(zhuǎn)角度并結(jié)合藍(lán)圖中的Lerp線性插值節(jié)點(diǎn)來實(shí)現(xiàn)移動(dòng)。為什么不直接用Vector軌道做移動(dòng)因?yàn)橛肍loatLerp的組合更靈活它清晰地分離了“動(dòng)畫進(jìn)度”和“目標(biāo)位置”方便我們后期修改移動(dòng)終點(diǎn)而無需重做曲線。2.3 曲線編輯控制動(dòng)畫的靈魂雙擊Timeline節(jié)點(diǎn)打開編輯窗口這里是你定義動(dòng)畫如何隨時(shí)間變化的地方。你可以右鍵添加“Float Track”。在曲線上點(diǎn)擊可以添加關(guān)鍵幀拖動(dòng)關(guān)鍵幀可以改變其時(shí)間和數(shù)值。右鍵關(guān)鍵幀可以設(shè)置插值模式自動(dòng)Auto曲線平滑過渡。線性Linear數(shù)值在關(guān)鍵幀間直線變化產(chǎn)生勻速運(yùn)動(dòng)。常量Constant數(shù)值保持不變直到下一個(gè)關(guān)鍵幀突然跳變適合制作閃爍效果。 例如要實(shí)現(xiàn)一個(gè)“先快后慢”的旋轉(zhuǎn)你可以設(shè)置0秒時(shí)角度為01秒時(shí)角度為90但將1秒處的關(guān)鍵幀插值模式調(diào)整使曲線前端陡峭、后端平緩。3. 實(shí)操準(zhǔn)備創(chuàng)建你的第一個(gè)可動(dòng)Actor藍(lán)圖理論清晰后我們進(jìn)入實(shí)戰(zhàn)。請(qǐng)打開你的UE5項(xiàng)目建議使用空白模板或Third Person模板進(jìn)行練習(xí)。3.1 創(chuàng)建藍(lán)圖與添加組件在內(nèi)容瀏覽器中右鍵選擇“藍(lán)圖類” - “Actor”。將其命名為BP_MovingPlatform移動(dòng)平臺(tái)或任何你喜歡的名字。雙擊打開這個(gè)藍(lán)圖首先進(jìn)入“事件圖表”Event Graph。我們需要一個(gè)可見的物體來代表我們的平臺(tái)。在“組件”面板中點(diǎn)擊“添加組件”Add Component搜索并添加一個(gè)Static Mesh Component靜態(tài)網(wǎng)格體組件。將其重命名為BaseMesh。在“細(xì)節(jié)”面板中找到BaseMesh組件為其指定一個(gè)靜態(tài)網(wǎng)格體。你可以使用引擎自帶的Cube立方體這樣看起來像一個(gè)平臺(tái)。同時(shí)建議將立方體的縮放Scale稍微調(diào)大比如設(shè)置為 (2.0, 2.0, 0.2)使其變成一個(gè)扁平的板子。注意為什么使用Actor藍(lán)圖而不是直接修改關(guān)卡中的物體因?yàn)樗{(lán)圖是可復(fù)用的資產(chǎn)。你制作好這個(gè)會(huì)動(dòng)的平臺(tái)后可以隨意拖拽到關(guān)卡的任何地方甚至復(fù)制多個(gè)每個(gè)都會(huì)獨(dú)立運(yùn)行自己的動(dòng)畫這是UE開發(fā)的基本模塊化思想。3.2 規(guī)劃動(dòng)畫參數(shù)在動(dòng)手連藍(lán)圖之前我們先明確要做什么旋轉(zhuǎn)動(dòng)畫讓平臺(tái)繞Z軸垂直軸從0度勻速旋轉(zhuǎn)到90度用時(shí)2秒。移動(dòng)動(dòng)畫讓平臺(tái)從起始位置水平移動(dòng)到另一個(gè)目標(biāo)位置用時(shí)3秒移動(dòng)過程是勻速的。我們需要在藍(lán)圖中創(chuàng)建幾個(gè)變量來存儲(chǔ)這些信息在“我的藍(lán)圖”面板創(chuàng)建以下變量RotationSpeed(Float)控制旋轉(zhuǎn)速度。我們可以通過Timeline輸出一個(gè)0到1的值乘以360度再乘以這個(gè)速度系數(shù)來控制旋轉(zhuǎn)。MoveDuration(Float)移動(dòng)動(dòng)畫的總時(shí)長(zhǎng)用于計(jì)算速度但本例中Timeline會(huì)接管時(shí)間控制。StartLocation(Vector)平臺(tái)的起始位置我們將在游戲運(yùn)行時(shí)獲取。TargetLocation(Vector)平臺(tái)要移動(dòng)到的目標(biāo)位置。這個(gè)我們可以在藍(lán)圖的“細(xì)節(jié)”面板中設(shè)置為“可編輯實(shí)例”Editable這樣每次把藍(lán)圖拖進(jìn)關(guān)卡后都能單獨(dú)設(shè)置每個(gè)平臺(tái)的移動(dòng)終點(diǎn)非常靈活。將TargetLocation的變量細(xì)節(jié)中的“實(shí)例可編輯”Instance Editable勾選上。4. 藍(lán)圖實(shí)現(xiàn)一步步構(gòu)建旋轉(zhuǎn)與移動(dòng)邏輯現(xiàn)在讓我們進(jìn)入最核心的藍(lán)圖連接部分。請(qǐng)打開BP_MovingPlatform的“事件圖表”。4.1 創(chuàng)建并設(shè)置Timeline節(jié)點(diǎn)在圖表中右鍵搜索“Timeline”添加一個(gè)節(jié)點(diǎn)將其重命名為TL_RotateAndMove。雙擊該節(jié)點(diǎn)打開編輯窗口。我們需要添加兩條軌道Float軌道重命名為RotationAlpha。這條曲線將輸出一個(gè)0到1的值。我們將0秒處的值設(shè)為02秒處的值設(shè)為1。將插值模式都設(shè)為“線性”Linear這樣會(huì)得到一個(gè)勻速增長(zhǎng)的數(shù)值。Float軌道重命名為MoveAlpha。這條曲線將輸出另一個(gè)0到1的值。我們將0秒處的值設(shè)為03秒處的值設(shè)為1。同樣使用線性插值??蛇xEvent軌道在3秒處移動(dòng)動(dòng)畫結(jié)束點(diǎn)添加一個(gè)事件命名為OnMoveComplete。這可以用來在移動(dòng)結(jié)束后觸發(fā)其他邏輯比如暫停幾秒再返回。關(guān)閉Timeline編輯窗口。你會(huì)看到藍(lán)圖中的Timeline節(jié)點(diǎn)現(xiàn)在有兩個(gè)輸出引腳RotationAlpha (Float)和MoveAlpha (Float)以及一個(gè)事件輸出OnMoveComplete。4.2 實(shí)現(xiàn)旋轉(zhuǎn)邏輯旋轉(zhuǎn)的邏輯是每一幀根據(jù)Timeline輸出的RotationAlpha值0到1計(jì)算出當(dāng)前幀應(yīng)該旋轉(zhuǎn)到的角度然后設(shè)置給網(wǎng)格體。從RotationAlpha引腳拉出引線搜索“Float * Float”節(jié)點(diǎn)。在第一個(gè)輸入口連接RotationAlpha第二個(gè)輸入口輸入360.0表示360度。這個(gè)乘法結(jié)果表示從0度到360度的進(jìn)度角度。如果你希望控制旋轉(zhuǎn)速度可以再乘以前面創(chuàng)建的變量RotationSpeed。從“我的藍(lán)圖”面板拖拽RotationSpeed變量到圖表選擇“獲取”Get然后與上一步的結(jié)果相乘?,F(xiàn)在我們得到了一個(gè)目標(biāo)角度例如當(dāng)Alpha0.5Speed1時(shí)角度是180度。我們需要將這個(gè)角度應(yīng)用到物體的旋轉(zhuǎn)上。但是直接設(shè)置絕對(duì)旋轉(zhuǎn)可能會(huì)與物理或其他動(dòng)畫沖突。更常見的做法是每幀在上一幀旋轉(zhuǎn)的基礎(chǔ)上增加一個(gè)增量。然而為了教程清晰我們采用另一種更直觀的方法使用Make Rotator和Set Actor Rotation。從RotationAlpha * 360.0的結(jié)果拉出引線搜索“Make Rotator”。這個(gè)節(jié)點(diǎn)可以創(chuàng)建旋轉(zhuǎn)器。我們只想繞Z軸旋轉(zhuǎn)所以將“Yaw”偏航角即繞Z軸旋轉(zhuǎn)引腳連接我們的角度計(jì)算結(jié)果“Pitch”和“Roll”保持為0。從“Make Rotator”的輸出引腳拉出引線搜索“Set Actor Rotation”。將這個(gè)節(jié)點(diǎn)連接到Timeline的“Update”事件輸出引腳上。這樣每一幀Timeline更新時(shí)都會(huì)用計(jì)算出的新旋轉(zhuǎn)角度來設(shè)置整個(gè)Actor的旋轉(zhuǎn)。實(shí)操心得這里用Set Actor Rotation是為了演示簡(jiǎn)單。在實(shí)際項(xiàng)目中如果只是旋轉(zhuǎn)某個(gè)子組件比如門板而不是整個(gè)Actor應(yīng)該使用組件的Set World Rotation或Set Relative Rotation。直接設(shè)置Actor旋轉(zhuǎn)會(huì)影響其所有子組件。4.3 實(shí)現(xiàn)移動(dòng)邏輯使用Lerp移動(dòng)的邏輯是每一幀根據(jù)Timeline輸出的MoveAlpha值0到1在起始位置StartLocation和目標(biāo)位置TargetLocation之間進(jìn)行線性插值Lerp然后將結(jié)果位置設(shè)置給Actor。首先我們需要在游戲開始時(shí)記錄下Actor的初始位置作為StartLocation。從事件圖表中的“Event BeginPlay”節(jié)點(diǎn)拉出引線搜索“Get Actor Location”然后拖拽StartLocation變量到圖表選擇“設(shè)置”Set將獲取到的位置賦值給它。現(xiàn)在處理移動(dòng)。從MoveAlpha引腳拉出引線搜索“Lerp (Vector)”。這個(gè)節(jié)點(diǎn)需要三個(gè)輸入A起點(diǎn)B終點(diǎn)Alpha插值比例0-1。將StartLocation變量獲取連接到A引腳。將TargetLocation變量獲取連接到B引腳。將MoveAlpha連接到Alpha引腳。“Lerp (Vector)”節(jié)點(diǎn)的輸出結(jié)果就是當(dāng)前幀Actor應(yīng)該處于的位置。從這個(gè)輸出引腳拉出引線搜索“Set Actor Location”。將“Set Actor Location”節(jié)點(diǎn)也連接到Timeline的“Update”事件輸出引腳上。這樣旋轉(zhuǎn)和移動(dòng)的設(shè)置會(huì)在同一幀更新。4.4 啟動(dòng)動(dòng)畫最后我們需要一個(gè)事件來觸發(fā)動(dòng)畫播放。最簡(jiǎn)單的方式是讓它在游戲開始后就自動(dòng)播放。從“Event BeginPlay”節(jié)點(diǎn)拉出執(zhí)行線連接到Timeline節(jié)點(diǎn)的“Play”或“Play from Start”引腳。我推薦使用“Play from Start”確保每次游戲運(yùn)行時(shí)動(dòng)畫都從頭開始。如果你希望動(dòng)畫循環(huán)播放可以雙擊Timeline節(jié)點(diǎn)在屬性面板中勾選“循環(huán)”Looping。這樣當(dāng)時(shí)間軸播放到終點(diǎn)后會(huì)自動(dòng)跳回起點(diǎn)繼續(xù)播放。至此核心藍(lán)圖連接完成。你的圖表應(yīng)該大致包含BeginPlay - Timeline PlayTimeline Update - Set Actor Rotation Set Actor LocationTimeline 輸出引腳連接到相應(yīng)的計(jì)算節(jié)點(diǎn)。5. 測(cè)試、優(yōu)化與問題排查藍(lán)圖連好了趕緊把它拖到關(guān)卡里測(cè)試一下吧5.1 在關(guān)卡中測(cè)試與配置保存并編譯你的BP_MovingPlatform藍(lán)圖。在關(guān)卡視口中從內(nèi)容瀏覽器將藍(lán)圖拖拽到場(chǎng)景中。選中剛放置的平臺(tái)實(shí)例在“細(xì)節(jié)”面板中你應(yīng)該能看到“Target Location”這個(gè)變量因?yàn)槲覀冎肮催x了“實(shí)例可編輯”。點(diǎn)擊這個(gè)向量值旁邊的“小吸管”圖標(biāo)然后在關(guān)卡視口中點(diǎn)擊你想要平臺(tái)移動(dòng)到的目標(biāo)位置。你也可以手動(dòng)輸入坐標(biāo)。點(diǎn)擊編輯器工具欄上的“運(yùn)行”Play按鈕。你應(yīng)該能看到立方體平臺(tái)一邊旋轉(zhuǎn)一邊向你設(shè)定的目標(biāo)位置移動(dòng)。5.2 常見問題與解決方案實(shí)錄在實(shí)際操作中你可能會(huì)遇到以下問題問題現(xiàn)象可能原因解決方案平臺(tái)根本不移動(dòng)/旋轉(zhuǎn)1. Timeline沒有啟動(dòng)。2. “Set Actor Location/Rotation”節(jié)點(diǎn)未連接到Timeline的Update事件。3. 組件繼承關(guān)系錯(cuò)誤。1. 檢查“Event BeginPlay”是否正確連接到Timeline的Play引腳。2. 確保所有設(shè)置位置的邏輯線都連到了Timeline的“Update”執(zhí)行引腳上。3. 如果你旋轉(zhuǎn)/移動(dòng)的是子組件如BaseMesh請(qǐng)使用Set World Location/Rotation節(jié)點(diǎn)并將“Component”引腳連接到你的網(wǎng)格體組件上而不是使用Actor級(jí)別的設(shè)置節(jié)點(diǎn)。移動(dòng)路徑是直線但方向不對(duì)StartLocation記錄的不是初始位置。確?!癊vent BeginPlay”時(shí)執(zhí)行的“Set StartLocation”邏輯在Timeline播放之前。最好將“Set StartLocation”節(jié)點(diǎn)直接連在BeginPlay和Timeline Play節(jié)點(diǎn)之間。旋轉(zhuǎn)軸不對(duì)比如繞X軸轉(zhuǎn)在“Make Rotator”節(jié)點(diǎn)中錯(cuò)誤地將角度值連給了Pitch或Roll。檢查“Make Rotator”節(jié)點(diǎn)的連接。繞垂直軸旋轉(zhuǎn)應(yīng)使用Yaw引腳。Pitch是繞X軸前后翻轉(zhuǎn)Roll是繞Y軸左右傾斜。動(dòng)畫播放一次后就停止了Timeline沒有設(shè)置為循環(huán)且沒有其他邏輯觸發(fā)它再次播放。如果需要循環(huán)在Timeline屬性中勾選“Looping”。如果需要往返運(yùn)動(dòng)可以創(chuàng)建兩條曲線或者使用Event軌道在動(dòng)畫結(jié)束時(shí)觸發(fā)“Reverse”播放。移動(dòng)過程中物體抖動(dòng)或閃爍每幀設(shè)置的位置/旋轉(zhuǎn)與物理或其它系統(tǒng)沖突。對(duì)于移動(dòng)可以考慮使用Add Actor World Offset代替Set Actor Location它是相對(duì)移動(dòng)有時(shí)更平滑。但核心思路不變。確保沒有啟用物理模擬Physics Simulation否則位置會(huì)被物理引擎覆蓋。5.3 性能與進(jìn)階優(yōu)化提示Tick與性能我們的邏輯連在Timeline的Update上而Timeline的播放又依賴于Actor的Tick每幀更新。對(duì)于大量這樣的動(dòng)態(tài)物體Tick會(huì)帶來性能開銷。一個(gè)優(yōu)化方法是僅在Timeline播放期間啟用Tick??梢栽赑lay Timeline時(shí)啟用TickSet Actor Tick Enabled在Timeline Finished事件中關(guān)閉Tick。使用向量曲線簡(jiǎn)化移動(dòng)對(duì)于簡(jiǎn)單的兩點(diǎn)間直線移動(dòng)用FloatLerp很清晰。但如果移動(dòng)路徑是復(fù)雜的曲線比如一個(gè)弧形直接在Timeline里編輯一條Vector曲線會(huì)更方便。在0秒處設(shè)置起點(diǎn)坐標(biāo)在N秒處設(shè)置終點(diǎn)坐標(biāo)中間可以插入關(guān)鍵幀來改變路徑。輸出后直接用Set Actor Location無需Lerp計(jì)算。藍(lán)圖與C通信標(biāo)題熱詞中提到了“ue藍(lán)圖和c互相通信”。對(duì)于此類簡(jiǎn)單的演示純藍(lán)圖完全夠用。但如果這個(gè)移動(dòng)平臺(tái)是復(fù)雜游戲機(jī)制的一部分其核心參數(shù)如速度、目標(biāo)點(diǎn)可能需要由C端的游戲邏輯來動(dòng)態(tài)計(jì)算和傳遞。這時(shí)你可以在C類中暴露一些函數(shù)或變量在藍(lán)圖中調(diào)用它們通過“Call Function”節(jié)點(diǎn)選擇父類函數(shù)實(shí)現(xiàn)更高效、更可控的邏輯。