Unity之PlayableGraph实现动画的正播和倒播

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

Unity之PlayableGraph实现动画的正播和倒播
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 PlayableGraph 动画播放

为初学者节省宝贵的学习时间,避免困惑!


前言:

  通过Playable API来控制动画的播放,这种方式比使用传统的Animation组件或Animator组件更加灵活,可以实现更复杂的动画控制逻辑。这篇博客将想你展示用Playable API来实现动画的正播和倒播。

在这里插入图片描述


文章目录

  • 一、创建Playable图
  • 二、创建Playable输出节点
  • 三、创建Playable动画剪辑
  • 四、设置输出节点的输入源为动画剪辑
  • 五、动画正播
  • 六、动画倒播


一、创建Playable图


/// <summary>
/// 创建PlayableGraph和设置
/// </summary>//创建一个PlayableGraph
PlayableGraph graph = PlayableGraph.Create();//设置PlayableGraph的时间更新方式graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);

创建PlayableGraph相当于在Unity中创建Timeline。

在这里插入图片描述


二、创建Playable输出节点


/// <summary>
/// 向PlayableGraph中添加AnimationTrack
/// </summary>
AnimationPlayableOutput.Create(PlayableGraph graph, string outName, Animator animator);

创建Playable输出节点相当于在Timeline中添加一个Animation Track。

在这里插入图片描述


三、创建Playable动画剪辑


/// <summary>
/// 向PlayableGraph中添加动画片段
/// </summary>
AnimationClipPlayable.Create(PlayableGraph graph, AnimationClip clip);

创建Playable动画剪辑相当于在Timelime中添加一个动画片段。

在这里插入图片描述


四、设置输出节点的输入源为动画剪辑


/// <summary>
/// 将动画剪辑绑定到输出节点上
/// </summary>
AnimationPlayableOutput.SetSourcePlayable(AnimationClipPlayable  clipPlayable);

设置输出节点的输入源为动画剪辑相当于将动画片段添加到Animator中。

在这里插入图片描述


五、动画正播

//设置为正向播放
AnimationClipPlayable.SetSpeed(1);
//设置为从开始时间进行播放
AnimationClipPlayable.SetTime(0);
//连线(设置输出节点的输入源为动画剪辑)
AnimationPlayableOutput.SetSourcePlayable(AnimationClipPlayable  clipPlayable);
//播放graph
PlayableGraph.Play();

通过设置动画片段的播放速度为1,表示为向前播放,同时设置播放的开始时间为动画片段的开始时间,开始播放graph时,动画正向播放。



六、动画倒播

//设置反正向播放
AnimationClipPlayable.SetSpeed(-1);
//设置为从结束时间进行播放
AnimationClipPlayable.SetTime(AnimationClipPlayable.GetAnimationClip().length);
//连线(设置输出节点的输入源为动画剪辑)
output.SetSourcePlayable(clipPlayable);
//播放graph
graph.Play();

通过设置动画片段的播放速度为-1,表示为向后播放,同时设置播放的开始时间为动画片段的结束时间,开始播放graph时,动画反向播放。


下面是动画的正反播放的完整代码:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;/// <summary>
/// 动画播放接口
/// </summary>
public interface IAnimationPlay
{void PlayForward(Action OnPlayCall=null, Action OnCompleted = null);void PlayBackward(Action OnPlayCall = null, Action OnCompleted = null);void Stop(Action OnStopCall = null);bool IsPlaying { get; }
}/// <summary>
/// 异步等待器
/// </summary>
public class AsyncWaitUntil
{private TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();bool completed = false;public AsyncWaitUntil(Func<bool> predicate){WaitUntil(predicate);}public Task Task => tcs.Task;private async void WaitUntil(Func<bool> predicate){while (!completed){completed = predicate.Invoke();await Task.Delay(200);}tcs.SetResult(null);}
}public class PlayableGraphAnimator : MonoBehaviour, IAnimationPlay, IAnimationClipSource
{public Animator animator;public AnimationClip clip;protected PlayableGraph graph;protected AnimationPlayableOutput output;public bool IsPlaying { get { return graph.IsPlaying(); } }private void Awake(){CrateGraph();}/// <summary>/// 初始化一个Graph/// </summary>private void CrateGraph(){graph = CreatePlayableGraph();output = CreatePlayableOutput(graph, "Animation", animator);}/// <summary>/// 创建PlayableGraph和设置/// </summary>private PlayableGraph CreatePlayableGraph(){//创建一个PlayableGraphPlayableGraph graph = PlayableGraph.Create();//设置PlayableGraph的时间更新方式graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);return graph;}/// <summary>/// 向PlayableGraph中添加AnimationTrack/// </summary>/// <param name="graph">PlayableGraph</param>/// <param name="outName">AnimationTrack的名称</param>/// <param name="animator">要添加的Track的类型</param>/// <returns></returns>private AnimationPlayableOutput CreatePlayableOutput(PlayableGraph graph, string outName, Animator animator){return AnimationPlayableOutput.Create(graph, outName, animator);}/// <summary>/// 向PlayableGraph中添加动画片段/// </summary>/// <param name="graph">PlayableGraph</param>/// <param name="clip">动画片段</param>/// <returns></returns>private AnimationClipPlayable CreateClipPlayable(PlayableGraph graph, AnimationClip clip){return AnimationClipPlayable.Create(graph, clip);}/// <summary>/// 向前播放动画/// </summary>/// <param name="OnPlayCall">开始播放回调</param>/// <param name="OnCompleted">播放完成回调</param>public async void PlayForward(Action OnPlayCall = null, Action OnCompleted = null){if (IsPlaying) return;var clipPlayable = CreateClipPlayable(graph, clip);//正向播放clipPlayable.SetSpeed(1);clipPlayable.SetTime(0);output.SetSourcePlayable(clipPlayable);graph.Play();OnPlayCall?.Invoke();await new AsyncWaitUntil(() => clipPlayable.GetTime() >= clip.length).Task;OnCompleted?.Invoke();graph.Stop();}/// <summary>/// 向后播放动画/// </summary>/// <param name="OnPlayCall">开始播放回调</param>/// <param name="OnCompleted">播放完成回调</param>public async void PlayBackward(Action OnPlayCall = null, Action OnCompleted = null){if (IsPlaying) return;var clipPlayable = CreateClipPlayable(graph, clip);//反向播放clipPlayable.SetSpeed(-1);clipPlayable.SetTime(clipPlayable.GetAnimationClip().length);output.SetSourcePlayable(clipPlayable);graph.Play();OnPlayCall?.Invoke();await new AsyncWaitUntil(() => clipPlayable.GetTime() <= 0).Task;OnCompleted?.Invoke();graph.Stop();}/// <summary>/// 停止动画/// </summary>public void Stop(Action OnStopCall = null){if (!IsPlaying) return;graph.Stop();OnStopCall?.Invoke();}public void GetAnimationClips(List<AnimationClip> results){if (clip != null)results.Add(clip);}private void OnDestroy(){graph.Destroy();}
}




TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步

END
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/808362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3d模型有边界框怎么去除---模大狮模型网

在3D建模软件中&#xff0c;边界框通常是用来表示模型的边界和外轮廓的&#xff0c;但有时候在渲染或导出模型时可能不希望显示这些边界框。以下是一些去除3D模型边界框的方法&#xff1a; 隐藏边界框选项&#xff1a; 在大多数3D建模软件中&#xff0c;边界框的显示可以通过简…

【从浅学到熟知Linux】冯诺依曼体系结构及进程概念详谈!

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 冯诺依曼体系结构操作系统如何理解管理操作系统概念设计操作系统目的系统调用和库函数概念 进程基本概念描…

移位寄存器

移位寄存器是如何工作的&#xff1f; 移位寄存器按照移位方向可分为左移位寄存器、右移位寄存器、双向移位寄存器。图11-15所示为用D触发器构成的4位左移位寄存器。待存数码由触发器F0的输入端D0输入&#xff0c;在移位脉冲作用下&#xff0c;可将数码从高位到低位向左逐步移入…

基于springboot+vue实现的艺术水平考级报名管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

信息收集笔记

1 简介 渗透的本质是信息收集 信息收集也叫做资产收集 信息收集是渗透测试的前期主要工作&#xff0c;是非常重要的环节&#xff0c;收集足够多的信息才能方便接下来的测试&#xff0c;信息收集主要是收集网站的域名信息、子域名信息、目标网站信息、目标网站真实IP、敏感/目…

2024.4.8Morris中序遍历(线索二叉树)学习

这次博主在学习完知识点和代码之后&#xff0c;准备对这个知识重新进行整理总结。站在一个初学者的角度来看待这个知识点&#xff0c;在他人的讲解基础上加一点点自己的理解&#xff0c;并记录下来。以加深自己的理解&#xff0c;并且希望能够帮助到你。博主是一个初学者&#…

HeidiSQL下载安装使用

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

互联网需要做安全防护吗?

互联网需要做安全防护&#xff0c;因为网络攻击的风险随时存在。一旦遭受大规模攻击&#xff0c;企业很可能会受到严重影响&#xff0c;甚至会造成巨大的经济损失和品牌声誉受损。因此&#xff0c;建议企业在安全防护方面做好以下几点&#xff1a; 加强网络安全意识教育&#x…

设备基础命令,路由基础

直连路由 静态路由 动态路由 根据路由器学习路由信息、生成并维护路由表的方法包括直连路由(Direct)、静态路由(Static)和动态路由(Dynamic)。直连路由&#xff1a;路由器接口所连接的子网的路由方式称为直连路由&#xff1b;非直连路由&#xff1a;通过路由协议从别的路由器…

2024年4月12日 十二生肖 今日运势

小运播报&#xff1a;2024年4月12日&#xff0c;星期五&#xff0c;农历三月初四 &#xff08;甲辰年戊辰月丙午日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;羊、狗、虎 需要注意&#xff1a;牛、马、鼠 喜神方位&#xff1a;西南方 财神方位&#xff1a;…

“安全边际大师”卡拉曼2023年珍贵访谈:如果视市场为狂躁的交易对手,那你就能利用反复无常来获利

“对于那些被广泛跟踪的股票&#xff0c;如果你不比其他人更聪明&#xff0c;且你的观点与别人无异&#xff0c;你是赚不到钱的。” “足够大的折价也许可以抵消你对它缺乏最深刻的认识。” “拓宽投资视野不仅诱人&#xff0c;也可能价值连城。” “如果向市场寻求答案&…

欢迎加入PenPad Season 2 ,获得勋章以及海量 Scroll 生态权益

PenPad 是 Scroll 生态中的首个 LaunchPad 平台&#xff0c;该平台继承了 Scroll 生态的技术优势&#xff0c;具备包括隐私在内的系列特点&#xff0c;同时且也被认为是 Scroll 生态最重要的价值入口之一。Penpad 与 Scroll 官方始终保持着合作&#xff0c;同时该项目自启动以来…

基于Springboot的网上商品订单转手系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的网上商品订单转手系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

无人机概述

1、中英文对照表 中文中文简称英文全称英文简称无人驾驶飞机无人机Unmanned Aerial VehicleUAV无人机自组织网络无人机网络flying Ad-Hoc networkFANET 2、相关概念 2.1鲁棒性 网络鲁棒性是指网络系统在面对随机故障、蓄意攻击或其他异常情况时&#xff0c;能够保持其基本功…

智慧工地管理平台源码:提供专业落地的解决方案

目录 智慧工地平台功能简介 一、劳务实名制系统 二、智能塔吊可视系统 三、视频监控&#xff08;含安全行为识别&#xff09; 四、环境监测&#xff08;联动自动喷淋&#xff09; 五、起重机械管控&#xff08;含吊钩可视化&#xff09; 六、升降电梯智能管控 七、高支…

鸿蒙让我赚到了第一笔桶金!年薪33.6W!

抢人&#xff01;抢人&#xff01;抢人&#xff01; 所谓抢滩鸿蒙&#xff0c;人才先行。鸿蒙系统火力全开后&#xff0c;抢人已成鸿蒙市场的主题词&#xff01; 智联招聘数据显示&#xff0c;春节后首周&#xff0c;鸿蒙相关职位数同比增长163%&#xff0c;是去年同期的2.6倍…

【C++算法】线性DP详解:数字三角形、最长上升子序列、最长公共子序列、最长公共子串、字符串编辑距离

文章目录 1&#xff09;数字三角形1&#xff1a;顺推2&#xff1a;逆推 2&#xff09;最长上升子序列1&#xff1a;线性DP做法2&#xff1a;二分优化 3&#xff09;最长公共子序列4&#xff09;最长公共子串5&#xff09;字符串编辑距离 1&#xff09;数字三角形 1&#xff1a…

股票高胜率的交易法则是什么?

股票交易中的高胜率交易法则并非一成不变&#xff0c;而是根据市场状况、个人投资风格和经验等多种因素综合而定的。以下是一些有助于提升交易胜率的法则和策略&#xff1a; 1.趋势跟踪法则&#xff1a;在股票交易中&#xff0c;趋势跟踪是一种有效的策略。通过观察大盘和个股…

Hadoop安装部署-NameNode高可用版

Hadoop分布式文件系统支持NameNode的高可用性&#xff0c;本文主要描述NameNode多节点高可用性的安装部署。 如上所示&#xff0c;Hadoop分布式文件系统部署了NameNode的Master主节点以及NameNode的Slave副节点&#xff0c;当Master主节点发生故障变得不可用时&#xff0c;ZooK…

llama-factory SFT系列教程 (一),大模型 API 部署与使用

文章目录 背景简介难点 前置条件1. 大模型 api 部署下一步阅读 背景 本来今天没有计划学 llama-factory&#xff0c;逐步跟着github的文档走&#xff0c;发现这框架确实挺方便&#xff0c;逐渐掌握了一些。 最近想使用 SFT 微调大模型&#xff0c;llama-factory 是使用非常广泛…