用Timeline实现动画特写(下)

https://www.bilibili.com/read/cv4145535?from=articleDetail

大渣好。说书人放了无穷久的鸽子之后又回来了。 空中三百六十度回旋磕头以表歉意 书接上一回,上一篇介绍了Timeline的部分基础知识,并实现了主角的动画播放,本篇将接着把剩余的功能实现。本篇主要介绍实现的方法,具体的手感参数还需小伙伴们根据自己的动画慢慢调哦(体力活)。与格挡结合后效果图如下: 本篇实现功能: 1.Timeline控制角色位移 2.切换特写镜头 3.触发镜头抖动和播放粒子特效 4.子弹时间 5.动态绑定轨道对象(Binding) 本文不包含格挡与切割内容,有兴趣的小伙伴自行参考底部链接。 一、Timeline Signals Unity 2019.1版本推出了Timeline Signals功能,具有“广播”特点,帮助发送事件。接下来将通过实现部分功能来熟悉Timeline Signals。 概念速览: 1.Signal Emitter(信号发射器) 信号发射器会放在Timeline上,它包含对信号资源的引用。如果当前播放时间点比发射器所在的时间点后,发射器会把信号资源发送到信号接收器。 (1)添加:对应Track右键 -> Add Signal Emitter (2)Signal Emitter面板简介 Retroactive: 开始播放时的进度位置在发射器后也能回溯触发。 Emit Once:循环播放时只触发一次。 Create Signal:新建信号资源。 Add Signal Receiver:添加信号接收器。 2.Signal Asset(信号资源) 信号资源是发射器和接收器之间的联系。通常信号资源会用作标识符。 已有Signal信号资源时,新建或切换Signal如下图: 3.Signal Receiver(信号接收器) 当接收器知道信号已被触发时,它会激活关联到对应信号资源的反应。Signal Receiver会自动添加到绑定对象(轨道左侧)上。添加信号反应操作如下图: 大概逻辑:播放到信号发射器处 -> 发射信号 -> 对应信号的接收器激活反应 此外,还可以通过编写Marker脚本自定义标记,有兴趣的小伙伴自行了解。 二、设置被击退位移 上一篇结尾“组合”出敌人被击退的动画,现在开始通过Transform Tween Track和Signals设置击退的位移。(也可以通过点击小红点录制实现位移) Ps:本文命名只是为了增加辨识度,无其他特殊含义。 1.添加Transform Tween Track (1)添加Track:Timeline编辑器空白处右键 > Transform Tween Track,命名为ETransformTrack。(Inspector窗口可重命名) (2)添加Clip:右键该Track > Add Transform Tween Clip,命名为BackTransClip。 (3)用Track Group(空白处右键)把主角和敌人的轨道分别装起来,便于整理。 (4)Transform Tween Clip部分属性简介: Tween Positon:是否转换Position。 Tween Rotation:是否转换Rotation。 Twee Type(转换类型):Linear线性匀速、Deceleration减速、Harmonic(中间最快)、Custiom自定义。 Start Location:Clip起始的Transform。 End Location:Clip结束的Transform。 (5)给所有轨道左侧绑定框拖进对应的对象。 2.设置Transform Tween Track 在敌人被攻击的时候,通过给Start Location和End Location赋值来实现击退位移动。 (1)方法一(速览即可):脚本中通过层层遍历找到Location,然后为其赋值,有兴趣的小伙伴自行研究。 大概思路如下: (2)方法二(本文粗暴做法): ①在主角里新建一个空的GameObject,命名为KickEndTrans,作为敌人被击退位移结束的Transform参考。 ②另外在Hierarchy再建一个空的GameObject,命名为TempKickEndTrans,拖进BackTransClip的End Location。 ③播放BackTransClip(Transform Tween Clip)前通过Signal调用方法,把TempKickEndTrans置到KickEndTrans的方位上,达到设置End Location的效果。(Start Location也如此设置) 代码如下: /// /// 设置敌人被击退后的Transform /// public void OnSignal_SetKickEndTrans() { //开始时敌人Transform tempTargetTrans.position = cPlayer.targetTrans.position;// cPlayer.targetTrans为当前敌人Transform tempTargetTrans.rotation = cPlayer.targetTrans.rotation; //结束时敌人Transform tempKickEndTrans.rotation = kickEndTrans.rotation; tempKickEndTrans.position = kickEndTrans.position; } ④使用Signal调用方法: 新建一个Signal Track,在开始击退前的位置添加Signal Emitter,添加信号,命名为Kick。 Hierarchy中新建一个空对象,命名为SignalFunctions,拖进Signal Track左侧绑定框,在SignalFunctions的Inspector窗口可以看到自动添加的Signal Receiver。 在Signal Receiver中选择对应信号,点击“+”添加反应,然后把方法所在对象拖进Reaction里,最后选择需要调用的方法。操作如图: 位移效果: 以上便是用Signal和Transform Tween Track 设置位移的粗暴做法,其他位移也可以如此设置,参数还需小伙伴们根据自己的动画具体情况具体分析。 三、镜头切换 镜头的切换主要是通过Cinemachine Track与Cinemachine配合完成的。 (1)基本概念 Cinemachine核心组件包括Brain和Virtual Camera(虚拟相机): Brain:负责相机的切换。 Virtual Camera(虚拟相机):负责拍摄。 Cinemachine提供了一些预设好行为方案,方便我们实现游戏中的功能。这次工程轨道中主要使用了Target Group Camera 和普通的Virtrual Camera,另外Timeline播放前人物用的是Free Look Camera(非本文主要介绍范围)。 Target Group Camera:可以在多个拍摄目标之间设置焦点,通过权重调节焦点偏移。 Virtrual Camera:普通的相机。 Free Look Camera:允许玩家控制并围绕目标旋转的相机,可以用作第三人称相机。 (2)设置Target Group Camera 脚踢敌人过程中使用的是Target Group Camera ,以主角和敌人综合得出拍摄焦点。 ①添加Target Group Camera后,Hierarchy窗口会出现一个CM vcam和一个对应的TargetGroup。关系如下图: ②调节TargetGroup 拍摄焦点通过目标、对应的权重以及半径综合得出。 Target:拍摄目标,本工程把玩家身上的摄像参考点拖进第一个参数框,通过脚本把敌人的Transform放进第二个参数框。 Weight:权重,用于调节焦点的偏移。 Radius:半径,用于调节相机距离。 在脚本中把敌人的Transform赋值给Target属性第二个参数框,代码如下(在播Timeline前调用),需要using Cinemachine; using Cinemachine; //... /// /// Timeline开始前设置Trans /// public void SetTransBeforeTL() { if (cPlayer.targetTrans) { //把敌人Trans赋值到Target Group组件里Target的第二个参数 targetGroup.m_Targets[1].target = cPlayer.targetTrans; //... } } (3)设置Cinemachine Track ①添加Track:Timeline编辑窗口空白处 > 右键 > Cinemachine Track。 ②把Main Camera拖进左侧绑定框。 ③添加Clip:把所需的cinemachine拖进轨道,按需排序和混合即可,播放时会随着进度自动切换,重叠处会自动过渡。 本工程的切换顺序(仅供参考):Free Look Camera(起始过渡) > Target Group Camera (脚踢过程)> Virtrual Camera(跳劈时在头顶) > Free Look Camera 四、触发镜头抖动与播放粒子特效 1.屏幕抖动 (1)需要用到的组件: ①Cinemachine Impulse Source:发出抖动信号。 ②Cinemachine Impulse Listener:收到信号,则镜头抖动。 (2)在Main Camera中添加Cinemachine Impulse Source组件:Inspector > Add Component > Cinemachine Impulse Source。 部分属性: Raw Signal:原始信号,可理解为抖动类型。使用Unity提供的信号类型:右侧齿轮 > Persets > 选择需要类型。 Amplitude Gain:振幅增益。 Frequency Gain:频率增益。 Impact Radius:影响半径。 (3)在需要抖动的Virtual Camera中添加Cinemachine Impulse Listener: Inspector > Cinemachine 组件(底部)> Add Extension > CinemachineImpulseListener。 2.粒子特效播放方法 在命中敌人的位置添加粒子特效,然后脚本中获取粒子特效,最后在方法中调用Play()播放。 public ParticleSystem hitRed_Kick; /// /// Kick特效 /// public void OnSignal_SetKickEffect() { hitRed_Kick.Play(); } 3.在攻击命中敌人的时候,通过Signal Receiver来触发镜头抖动和调用特效播放方法。 发出信号方法:CinemachineImpulseSource.GenerateImpulse(); 五、子弹时间 本次是通过调节时间的缩放来实现子弹时间。 1.添加Time Dilation Track。 2.添加Time Dilation Clip。部分属性: Time Scale:时间缩放比例,1为正常时间,0为静止。 Blend Curves:混合曲线。 3.调节思路 (1)创建两个Time Dilation Clip:一个Time Scale为0,另一个Time Scale为1。(参数自行调节) (2)把连个Clip重叠起来,通过调节Clip重叠长度和混合曲线,达到自己想要的效果。 六、动态绑定轨道对象 终结不同的敌人代表着动画的执行角色不同,因此需要在脚本中为轨道更换绑定的目标。 1.添加事件 (1)相关变量: using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.Playables;using UnityEngine.Timeline; public class PAnimation : MonoBehaviour{ CPlayer cPlayer; PSlicer pSlicer; //切割脚本 Animator animator; Animator targetAnimator; RuntimeAnimatorController player_AC; //记录玩家AnimatorController RuntimeAnimatorController target_AC; //记录目标AnimatorController public PlayableDirector playableDirector; //TimelineDirector; public TimelineAsset tL_StrikeBack; //反击的TimelineAsset //信号相关 SignalFunctions signalFunctions; //信号方法脚本 Dictionary bindingDict; //存储 //...} (2)事件 ①PlayableDirector.played:在PlayableDirector 开始播放时调用。 ②PlayableDirector.stopped:在PlayableDirector停止播放时调用。 void Start() { // ... //添加事件 playableDirector.played += OnPlayableDirectorStart; //开播时执行 playableDirector.stopped += OnPlayableDirectorStopped; //停播时执行 } 2.释放技能时: (1)指定播放片段(TimelineAsset)。 public void PlayTimeline() { //指定TimelineAsset(播放片段) playableDirector.playableAsset = tL_StrikeBack; //储存Binding SaveBindings(); playableDirector.Play(); } (2)用字典储存每个轨道:PlayableBinding.streamName 获取轨道名字,作为字典的Key。 代码如下(需要using UnityEngine.Playables;和using UnityEngine.Timeline;): using UnityEngine.Playables;using UnityEngine.Timeline;//... //储存绑定的Track左侧,换新TimelineAsset时调用 public void SaveBindings() { foreach (PlayableBinding binding in playableDirector.playableAsset.outputs) { if (!bindingDict.ContainsKey(binding.streamName)) { bindingDict.Add(binding.streamName, binding); } } } 3.Timeline播放前 (1)置空AnimatorController避免播放TimeLine过程中执行其他状态。(也可在动画状态机中添加表示正在播放Timeline的状态来解决) (2)通过检索字典给轨道绑定对象: 绑定轨道左侧对象:PlayableDirector.GetGenericBinding(Object key, Object value);。 Key:可用PlayableBinding.sourceObject获取。 Value:需要绑定的对象。 代码如下(含注释): /// /// 播放前执行 /// /// void OnPlayableDirectorStart(PlayableDirector aDirector) { cPlayer.characterController.enabled = false; //关闭CharacterController,不然有冲突 animator.applyRootMotion = true; //应用RootMotion //暂存AnimatorController player_AC = animator.runtimeAnimatorController; //把AnimatorController暂时置空,避免播Timeline时动画状态机还在执行其他状态。 animator.runtimeAnimatorController = null; //敌人AnimatorController暂时置空,播完置回去。 targetAnimator = cPlayer.targetTrans.GetComponent(); target_AC = targetAnimator.runtimeAnimatorController; targetAnimator.runtimeAnimatorController = null; //把玩家Animator绑进轨道 playableDirector.SetGenericBinding(bindingDict["PlayerAniTrack"].sourceObject, animator); playableDirector.SetGenericBinding(bindingDict["PTransformTrack"].sourceObject, animator.transform); //把敌人Animator绑进轨道 playableDirector.SetGenericBinding(bindingDict["EnemyAniTrack"].sourceObject, cPlayer.targetTrans.GetComponent()); playableDirector.SetGenericBinding(bindingDict["ETransformTrack"].sourceObject, cPlayer.targetTrans); //Clip 参考Trans设置 signalFunctions.SetTransBeforeTL(); } 4.动画播放完后,用PlayableDirector.Evaluate()估算Timeline中各对象,否则会回到开播的位置,然后把播放的TimelineAsset置为null。代码如下(含注释): /// /// 播放完执行 /// /// void OnPlayableDirectorStopped(PlayableDirector aDirector) { playableDirector.Evaluate(); //评估对象所在位置,否则回到播放前位置 playableDirector.playableAsset = null; //playableDirector里的TimlineAsset置Null //重置玩家播放Timeline前的状态 cPlayer.characterController.enabled = true; cPlayer.isStrikingBack = false; animator.applyRootMotion = false; animator.runtimeAnimatorController = player_AC; //重置敌人播放Timeline前的状态 if (targetAnimator) { targetAnimator.runtimeAnimatorController = target_AC; //... } } 5.踩过的坑 (1)角色身上CharacterController在激活状态,播放Timeline时角色会不能位移。 (2)结束播放时,没有执行PlayableDirector.Evaluate(),角色回到开始播放位置。 (3)播放结束,没有把PlayableDirector.playableAsset置空,非Apply Root Motion时角色不能移动。 结语:本文结合了Timeline Signals和各种Track实现了一系列的功能,虽然已花了较长时间查询资料,但是仍存在很多不完善的地方,时间关系只好先介绍到这里(自己开的坑,头发掉满地也只能含泪勉强填完)。希望对大家初步了解Timeline有所启发,如有问题欢迎讨论。 相关资料 1.Timeline Signals:https://connect.unity.com/p/shi-yong-unity-2019-1zhong-de-timeline-signals 2.Timeline动态赋值:https://zhuanlan.zhihu.com/p/29585350 3.Ezy-Slice切割教程:https://www.bilibili.com/video/av65373505 4.从SkinnedMeshRenderer获取正确显示的普通Mesh:https://blog.csdn.net/Traip/article/details/88095446 5.格挡:https://zhuanlan.zhihu.com/p/83607025 链接:https://pan.baidu.com/share/init?surl=K1RX_qmmPfcjQazJHpNBJA 提取码:stll 咱们的游戏开发交流群也欢迎强势插入:869551769 希望参与线下游戏开发学习的,欢~~~~~~迎访问:http://www.levelpp.com/

作者:皮皮关做游戏
https://www.bilibili.com/read/cv4145535?from=articleDetail
出处: bilibili

用Timeline实现动画特写(下)相关推荐

  1. Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写

    Silverlight中的HLSL不仅适用于场景与动画渲染,对于游戏中的角色,我们同样可以利用它制作动画特写.较常见的比如角色传送时的淡入淡出.扭曲变形.幻化呈现等切换动画,当然还有例如角色被DeBu ...

  2. 一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写

    Silverlight中的HLSL不仅适用于场景与动画渲染,对于游戏中的角色,我们同样可以利用它制作动画特写.较常见的比如角色传送时的淡入淡出.扭曲变形.幻化呈现等切换动画,当然还有例如角色被DeBu ...

  3. unity Timeline控制动画的播放

    unity Timeline控制动画的播放 创建一个空物体GameObject,添加Playable Director组件,添加脚本组件: 新建一个长方体: 创建timeline并将其拖到空物体的Pl ...

  4. CSS3动画 - title下划线的拉伸效果

    类似于 加载条 1. 效果图 2. 代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8&qu ...

  5. [0 to 0.5]从零开始学习Android动画知识(下)

    [0 to 0.5]从零开始学习Android动画知识(下) 矢量动画(Scalable Vector Graphics) 不同于前面的为控件做动画效果的方法,矢量动画则是为图形做出动画效果 矢量图 ...

  6. canvas 制作动画(下)

    canvas 制作动画(下) 1. 改变方向 在 canvas 制作动画(上)已经介绍了如何创建动画,但还没有讨论如何控制形状动画的方式.我觉得只有直线动画会让人觉得很枯燥,不知你是否也这样想. 你已 ...

  7. android listview下拉刷新动画,ListView下拉刷新实现方式详解和改造(上)

    我们知道页面的下拉刷新目前基本已经成为智能移动终端的标配刷新方式.Twitter设计出现有的下拉刷新(在2013年申请了专利). 下拉刷新1.jpg 这一优美而又简单的刷新方式,很快使得各大系统纷纷效 ...

  8. 【带着canvas去流浪(13)】用Three.js制作简易的MARVEL片头动画(下)#华为云·寻找黑马程序员#

    [摘要] three.js实现的Web 3D字体模型动画 示例代码托管在:http://www.github.com/dashnowords/blogs 有了上一篇基础知识的储备,本节就来制作一下简易 ...

  9. android 啦窗帘的动画,android 下拉窗帘效果

    [实例简介] [实例截图] [核心代码] public class CurtainView extends RelativeLayout implements OnTouchListener{ pri ...

最新文章

  1. 嵌入式系统在井下煤炭井下监控系统的应用
  2. oracle 监听程序当前无法识别连接描述符中请求的服务_最新版Web服务器项目详解 04 http连接处理(上)...
  3. 关于《用C#编写ActiveX控件》的几点说明
  4. js中的bool值转换及 、||、 !!详解
  5. 基于 registry 搭建 Docker 私有镜像仓库
  6. LED计数电路,5输入按键编码器,7段数码管显示驱动集成为LED计数测试电路
  7. centos7创建asm磁盘_ASM环境下防止误将数据文件扩容到本地文件系统的方法
  8. Excel2003怎样拆分单元格
  9. mysql数据库无法被其他ip访问的解决方法
  10. windows10彻底杀死卡死的顽固进程
  11. 数据预处理—7.数据插补之拉格朗日插值法、牛顿差值法及python实现
  12. 智能安防系统如何防火、防盗、防煤气?
  13. java 三次样条插值_java – 三次样条插值的正确实现
  14. U盘安装CentOS 7解决方案 (fat系统文件4g限制)
  15. 网站被封了要换服务器吗,网站被惩罚或被封该怎么办?
  16. 江民“网页收割者”病毒技术分析报告
  17. 复变函数题目(持续更新)
  18. 技术支持快递第6 期
  19. JavaSE —— 000基础版
  20. 2023年贵州大学文艺学专业考研上岸经验

热门文章

  1. 阿里云ECS服务器Linux环境下配置php服务器(一)--基础配置篇
  2. Oracle 11g+PLSQL Developer+SQL Developer+JDK 详细安装教程
  3. openfire服务器的配置
  4. java全月应纳税所得额_个人所得税应纳税所得额计算公式是什么?
  5. 0x0000000A 蓝屏问题
  6. 四通道数字隔离器π141E60 代替Si8641BB-B-IS
  7. 【PHP代码审计】站帮主CMS漏洞挖掘
  8. GEE(Google Earth Engine) 最基础代码学习笔记二 —— JavaScript 语言
  9. 深度学习图像处理:双线性CNN (Bilinear cnn)- 细粒度图像分类模型
  10. ntp服务器部署和配置文件