Unity動畫系統使用整理 --- Playable

???Playable API???是一個強大的工具,用于更靈活地控制動畫、音頻、腳本等時間軸內容的播放和混合。它提供了比傳統 Animator 更底層、更可控的方式管理時間軸行為,尤其適合復雜動畫邏輯或動態內容組合的場景。

優點:

1.Playables API 支持動態動畫混合,這意味著場景中的對象可以提供自己的動畫。例如,武器、寶箱和陷阱的動畫可以動態添加到 PlayableGraph 并使用一段時間。
2.Playables API 可播放單個動畫,而不會產生創建和管理 AnimatorController 資源所涉及的開銷
3.Playables API 允許用戶動態創建混合圖并直接逐幀控制混合權重
4.可在運行時創建 PlayableGraph,根據條件按需添加可播放節點。可量身定制 PlayableGraph 來適應當前情況的要求,而不是提供一個巨大的“一刀切”圖形來啟用和禁用節點。

核心機制:

核心類型??:

1.??PlayableGraph
動畫控制的核心容器,負責管理所有動畫節點(Playable)和輸出通道(PlayableOutput)。

PlayableGraph graph = PlayableGraph.Create("MyAnimationGraph");

2.??Playable??:
??所有可播放項的基類型??(如AnimationClipPlayable),使用struct實現??避免內存分配??。
??隱式轉換??子類型為Playable,但??反向需顯式轉換??(可能因類型不兼容拋出異常)。
3.PlayableOutput??:
輸出的基類型??
(如AnimationPlayableOutput),同樣為struct。
必須通過SetSourcePlayable()??鏈接到Playable??,否則無效果。

AnimationPlayableOutput output = AnimationPlayableOutput.Create(graph, "AnimationOutput", animator);

:Playable 和 PlayableOutput 未暴露大量方法。可使用PlayableExtensionsPlayableOutputExtensions靜態類提供的擴展方法。

創建與連接??:??

1.創建可播放項/輸出??
所有非抽象類型提供??靜態Create()方法??,首個參數為PlayableGraph(擁有該節點)。

var clipPlayable = AnimationClipPlayable.Create(graph, clip);
var output = AnimationPlayableOutput.Create(graph, "Output", animator);

2.??連接節點??
??節點間連接??:通過PlayableGraph.Connect(source, sourcePort, target, targetPort)。
??輸出綁定根節點??:output.SetSourcePlayable(rootPlayable)。

PlayableGraph管理??

??1.生命周期??
??創建??:PlayableGraph.Create("GraphName")。
??播放/停止??:graph.Play() / graph.Stop()。
??手動更新??:graph.Evaluate(deltaTime)(適用于非實時更新)。
??銷毀??:??必須手動調用??graph.Destroy(),否則報錯(自動銷毀其下所有節點)。

2.??注意事項??
??輸入限制??:某些Playable類型??不支持輸入連接??(如AnimationClipPlayable)。
??權重控制??:混合節點需通過SetInputWeight()管理權重。
??內存安全??:避免頻繁創建/銷毀,優先重用節點。

使用:

1.播放單個動畫

在角色物體掛載以下腳本,如圖:

代碼:

[RequireComponent(typeof(Animator))]
public class SimplePlayable: MonoBehaviour
{public Animator animator;public AnimationClip clip;private PlayableGraph graph;void Start(){graph = PlayableGraph.Create();this.CreateSimpleAnimation();graph.Play();}void OnDestroy(){if (graph.IsValid())graph.Destroy();}void CreateSimpleAnimation(){// 創建AnimationClipPlayablevar clipPlayable = AnimationClipPlayable.Create(graph, clip);// 創建輸出并連接到Animatorvar output = AnimationPlayableOutput.Create(graph, "Output", animator);output.SetSourcePlayable(clipPlayable);}
}

結果:

2.混合兩個動畫(Mixer)?

在角色物體上掛載以下腳本,如圖:

代碼:

[RequireComponent(typeof(Animator))]
public class MixerPlayable : MonoBehaviour
{public AnimationClip clip0;public AnimationClip clip1;[Range(0f, 1f)] public float weight;PlayableGraph playableGraph;AnimationMixerPlayable mixerPlayable;void Start(){// 創建該圖和混合器,然后將它們綁定到 Animator。playableGraph = PlayableGraph.Create();var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", GetComponent<Animator>());mixerPlayable = AnimationMixerPlayable.Create(playableGraph, 2); //2個輸入playableOutput.SetSourcePlayable(mixerPlayable);// 創建 AnimationClipPlayable 并將它們連接到混合器。var clipPlayable0 = AnimationClipPlayable.Create(playableGraph, clip0);var clipPlayable1 = AnimationClipPlayable.Create(playableGraph, clip1);// 連接動畫到MixerplayableGraph.Connect(clipPlayable0, 0, mixerPlayable, 0);playableGraph.Connect(clipPlayable1, 0, mixerPlayable, 1);//播放該圖。playableGraph.Play();}void Update(){// 設置混合權重(0表示全clip0,1表示全clip1)weight = Mathf.Clamp01(weight);mixerPlayable.SetInputWeight(0, 1.0f - weight);mixerPlayable.SetInputWeight(1, weight);}void OnDisable(){//銷毀該圖創建的所有可播放項和輸出。playableGraph.Destroy();}
}

結果:

3.分層動畫(LayerMixer)?

創建一個動畫遮罩

設置遮罩,如下圖,將疊加動畫的下半動畫不播放

將角色物體上掛載以下腳本,如下圖:

代碼:

[RequireComponent(typeof(Animator))]
public class LayerMixerPlayable : MonoBehaviour
{public AnimationClip runClip;public AnimationClip attackClip;public AvatarMask attackMask;PlayableGraph graph;void Start(){// 創建該圖和混合器,然后將它們綁定到 Animator。graph = PlayableGraph.Create();var playableOutput = AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>());AnimationLayerMixerPlayable layerMixer = AnimationLayerMixerPlayable.Create(graph, 2);playableOutput.SetSourcePlayable(layerMixer);// 基礎層(如移動)var baseLayer = AnimationClipPlayable.Create(graph, runClip);graph.Connect(baseLayer, 0, layerMixer, 0);layerMixer.SetInputWeight(0, 1f);// 疊加層(如攻擊)var attackLayer = AnimationClipPlayable.Create(graph, attackClip);graph.Connect(attackLayer, 0, layerMixer, 1);layerMixer.SetInputWeight(1, 1f);// 設置層級遮罩(可選)layerMixer.SetLayerMaskFromAvatarMask(1, attackMask); // 僅特定身體部位播放攻擊動畫graph.Play();}
}

結果:將一個跑的動畫和一個攻擊動畫混合,再將攻擊動畫的下半身添加動畫遮罩

4.動態創建與銷毀節點

// 動態添加新動畫
public void AddDynamicAnimation(AnimationClip clip)
{var newClipPlayable = AnimationClipPlayable.Create(graph, clip);mixer.AddInput(newClipPlayable, 0, 1f); // 假設mixer已存在
}// 銷毀節點
public void RemoveAnimation(int index)
{mixer.GetInput(index).Destroy();mixer.DisconnectInput(index);
}

創建自定義可播放項:

??1. 創建自定義 Playable????

繼承 PlayableBehaviour??:定義自定義邏輯需從基類 PlayableBehaviour 派生,重寫其方法(如 PrepareFrame, OnPlayableCreate 等)。

public class MyCustomPlayableBehaviour : PlayableBehaviour 
{// 實現自定義邏輯(如重寫幀更新方法)public override void PrepareFrame(Playable playable, FrameData info) {// 每幀執行邏輯}
}

可視化工具的安裝與使用:

性能優化

1.提前創建PlayableGraph??:在Awake()或Start()中初始化,避免運行時卡頓。
??2.重用Playable節點:??對于頻繁切換的動畫(如攻擊、受傷),預先創建節點并通過權重控制顯隱,而非反復創建/銷毀。
??3.限制更新頻率?:?若動畫無需每幀更新,可通過graph.Evaluate(deltaTime)手動控制更新。
??4.使用Playable TraversalMode??,設置遍歷模式優化性能:

graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
graph.SetPlayableTraversalMode(PlayableTraversalMode.Passthrough);

應用場景

??1.角色移動混合??:根據速度動態混合走、跑、沖刺動畫。
??2.受傷動畫疊加??:在基礎動畫上疊加受傷抖動,不影響其他身體部位。
??3.過場動畫控制??:結合Timeline和Playable API實現復雜的過場動畫序列。

注意事項

1.銷毀PlayableGraph??:在對象銷毀時調用graph.Destroy(),防止內存泄漏。
2.??動畫長度處理:??循環動畫需手動控制停止,或使用ClipPlayable.SetDuration()。
3.??權重歸一化??:混合時確保權重總和不超過1,避免動畫異常。
4.??版本兼容性:??Playable API在Unity 2017.1+中穩定,但部分功能(如ScriptPlayable<T>)可能需要更新版本。

未完待續。。。

參考鏈接:

Playables API - Unity 手冊

Unity - 手冊:Playables API (unity3d.com)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79577.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79577.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79577.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于STM32、HAL庫的BMP390L氣壓傳感器 驅動程序設計

一、簡介: BMP390L 是 Bosch Sensortec 生產的一款高精度氣壓傳感器,專為需要精確測量氣壓和海拔高度的應用場景設計。BMP390L 具有更低的功耗、更高的精度和更快的響應速度。 二、硬件接口: BMP390L 引腳STM32L4XX 引腳說明VDD3.3V電源GNDGND地SCLPB6 (I2C1 SCL)I2C 時鐘線…

Arduino快速入門

Arduino快速入門指南 一、硬件準備 選擇開發板&#xff1a; 推薦使用 Arduino UNO&#xff08;兼容性強&#xff0c;適合初學者&#xff09;&#xff0c;其他常見型號包括NANO&#xff08;體積小&#xff09;、Mega&#xff08;接口更多&#xff09;。準備基礎元件&#xff1a…

破解 Qt QProcess 在 Release 模式下的“卡死”之謎

在使用 Qt 的 QProcess 以調用外部 ffmpeg/ffprobe 進行音視頻處理時&#xff0c;常見的工作流程是&#xff1a; gatherParams&#xff1a;通過 ffprobe 同步獲取媒體文件的參數&#xff08;分辨率、采樣率、聲道數、碼率等&#xff09;。 reencode&#xff1a;逐個文件調用 f…

MySQL 中 UPDATE 結合 SELECT 和 UPDATE CASE WHEN 的示例

概述 以下是 MySQL 中 UPDATE 結合 SELECT 和 UPDATE CASE WHEN 的示例&#xff1a; 一、UPDATE 結合 SELECT&#xff08;跨表更新&#xff09; 場景&#xff1a;根據 orders 表中的訂單總金額&#xff0c;更新 users 表中用戶的 total_spent 字段。 -- 創建測試表 CREATE T…

【MCP】魔搭社區MCP服務(高德地圖、everything文件搜索)

【MCP】魔搭社區MCP服務&#xff08;高德地圖、everything文件搜索&#xff09; 1、上手使用2、環境配置&#xff08;1&#xff09;cherry-studio配置&#xff08;2&#xff09;添加魔搭大模型服務&#xff08;如果已經設置了其他大模型服務&#xff0c;可跳過&#xff09;&…

MapReduce 的工作原理

MapReduce 是一種分布式計算框架&#xff0c;用于處理和生成大規模數據集。它將任務分為兩個主要階段&#xff1a;Map 階段和 Reduce 階段。開發人員可以使用存儲在 HDFS 中的數據&#xff0c;編寫 Hadoop 的 MapReduce 任務&#xff0c;從而實現并行處理1。 MapReduce 的工作…

MCU開啟浮點計算FPU

FPU 測試 1. FPU 簡介2. 協處理器控制寄存器&#xff08;CPACR&#xff09;3. 開啟FPU4. 驗證FPU&#xff08;Julia 分形實驗&#xff09; 1. FPU 簡介 FPU 即浮點運算單元&#xff08;Float Point Unit&#xff09;。浮點運算&#xff0c;對于定點 CPU&#xff08;沒有 FPU 的…

進程相關面試題20道

一、基礎概念與原理 1.進程的定義及其與程序的本質區別是什么&#xff1f; 答案&#xff1a;進程是操作系統分配資源的基本單位&#xff0c;是程序在數據集合上的一次動態執行過程。核心區別&#xff1a;? 動態性&#xff1a;程序是靜態文件&#xff0c;進程是動態執行實例…

React Hooks 精要:從入門到精通的進階之路

Hooks 是 React 16.8 引入的革命性特性,它讓函數組件擁有了類組件的能力。以下是 React Hooks 的詳細使用指南。 一、基礎 Hooks 1. useState - 狀態管理 import { useState } from react;function Counter() {const [count, setCount] = useState(0); // 初始值為0return …

springboot3+vue3融合項目實戰-大事件文章管理系統-更新用戶頭像

大致分為三步 首先在usercontroller里面加入方法 PatchMapping ("/updateAvatar")public Result upadateAvatar(RequestParam URL String avatarUrl){userService.updateAvater(avatarUrl);return Result.success();}url注解能驗證傳入的url是不是合法的&#xff0c…

Mosaic數據增強技術

Mosaic 數據增強技術是一種在計算機視覺領域廣泛應用的數據增強方法。下面是Mosaic 數據增強技術原理的詳細介紹 一、原理 Mosaic 數據增強是將多張圖像&#xff08;通常是 4 張&#xff09;按照一定的規則拼接在一起&#xff0c;形成一張新的圖像。在拼接過程中&#xff0c;會…

Git安裝教程及常用命令

1. 安裝 Git Bash 下載 Git 安裝包 首先&#xff0c;訪問 Git 官方網站 下載適用于 Windows 的 Git 安裝包。 安裝步驟 啟動安裝程序&#xff1a;雙擊下載的 .exe 文件&#xff0c;啟動安裝程序。選擇安裝選項&#xff1a; 安裝路徑&#xff1a;可以選擇默認路徑&#xff0…

學習日志04 java

PTA上的練習復盤 java01 編程題作業感悟&#xff1a; 可以用ai指導自己怎么調試&#xff0c;但是不要把調代碼這過程里面的精華交給ai&#xff0c;就是自己去修正錯誤不能讓ai代勞&#xff01;~~~ 1 scanner.close() Scanner *** new Scanner(System.in); ***.close(); …

AI 在模仿歷史語言方面面臨挑戰:大型語言模型在生成歷史風格文本時的困境與研究進展

概述 在當今數字化時代&#xff0c;人工智能&#xff08;AI&#xff09;技術在諸多領域展現出了強大的能力&#xff0c;但在處理歷史語言這一特定任務時&#xff0c;卻遭遇了不小的挑戰。美國和加拿大的研究人員通過合作發現&#xff0c;像 ChatGPT 這樣的大型語言模型&#x…

基于 Spring Boot 瑞吉外賣系統開發(十二)

基于 Spring Boot 瑞吉外賣系統開發&#xff08;十二&#xff09; 菜品刪除 單擊“批量刪除”和“刪除”時&#xff0c;會攜帶需要刪除的菜品的id以delete請求方式向“/dish”發送請求。 URLhttp://127.0.0.1:8080/dish調用方法DELETE參數ids DishController添加刪除方法 …

Day22打卡-復習

復習日 仔細回顧一下之前21天的內容&#xff0c;沒跟上進度的同學補一下進度。 作業&#xff1a; 自行學習參考如何使用kaggle平臺&#xff0c;寫下使用注意點&#xff0c;并對下述比賽提交代碼 泰坦尼克號人員生還預測https://www.kaggle.com/competitions/titanic/overview K…

L48.【LeetCode題解】904. 水果成籃

目錄 1.題目 2.分析 方法1:暴力枚舉 方法2:暴力解法的優化:滑動窗口 代碼 方法3:優化方法2:使用數組充當哈希表 方法4:四個變量分別充當籃子和籃子中水果的個數(最快!!!) 代碼 容易忽略的點 1.題目 https://leetcode.cn/problems/fruit-into-baskets/ 你正在探訪一家農…

Leetcode-BFS問題

LeetCode-BFS問題 1.Floodfill問題 1.圖像渲染問題 [https://leetcode.cn/problems/flood-fill/description/](https://leetcode.cn/problems/flood-fill/description/) class Solution {public int[][] floodFill(int[][] image, int sr, int sc, int color) {//可以借助另一…

Typora+PicGo+Gitee圖床配置教程 自動圖片上傳

配置步驟 #mermaid-svg-aPUbWs43XR5Rh7vf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-icon{fill:#552222;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-text{fill:#552222;stroke:#552222;}#…

養生:開啟健康生活的全新篇章

養生是一場關乎生活品質與身心健康的持續修行&#xff0c;從飲食調養到運動鍛煉&#xff0c;從睡眠管理到心態塑造&#xff0c;每個環節都對健康有著深遠影響。以下為你提供全面且實用的養生指南。 飲食養生&#xff1a;科學膳食&#xff0c;滋養生命 合理的飲食是養生的根基…