0 前言

        早些时间学动画系统时的笔记,实际还没学完,后续计划会慢慢补全吧。

1 动画

        通常来说动画都是动画师来做的,不过Unity也能实现简单的动画效果。PS:官方文档中,将动画称之为动画剪辑。

1.1 创建动画

        首先在Unity中打开动画窗口。点击“菜单栏-Window-Animation-Animation”即可打开动画窗口,但此时窗口内是空的,此时若想要创建一个动画文件,需要先选中一个游戏对象。我们在场景中创建一个Cube然后选中,便可以看到在窗口内部出现一个创建按钮,点击创建即可,记得选好创建路径。过程如图:

之后我们就可以在Animation窗口中制作动画,同时在我们刚刚创建文件的路径中会生成如下两个文件:

Cube Animation是动画文件,就是我们接下来制作动画所操作的文件,Cube则是一个动画控制器文件,后续会讲。同时Cube上也会自动挂载一个组件:

先无视此组件,在后面会介绍。

1.2 制作动画

        首先来看下Animation窗口,主要说明几个常用部分。

此时在此窗口内,实际上就只是在编辑Cube Animation文件。

1.2.1 录制动画

        录制动画是比较简单的方式,在开启录制后,通过帧游标在不同时间处操作游戏对象,让Animation记录游戏对象的状态,进而实现动画效果。录制方式如下:

可以看到在录制时,我们一旦操作Cube,其被操作的属性就会被记录,且显示在属性窗口内。在我稍微拖动了下Cube,这时就在0时刻记录了Cube的状态(注意记录的是我操作后的状态,若起始不操作Cube,直接拖游标到后面操作,那么会自动将Cube最开始的状态记录到0时刻,同时在游标位置记录我操作后的状态),然后我将游标拖动到1s的位置,将Cube的位置调整到斜上方,Animation会自动记录下状态。之后结束录制,进行播放就可以看到动画效果了。
        除了位置外还可以调节Cube的Rotation、Scale等等。对于不满意的属性,我们也可以手动去属性窗口调整。这里不再过多介绍。

1.2.2 手动实现动画

        除了录制外,我们还可以手动添加属性,添加属性在某一时刻的帧,然后调整这一帧属性的值。可以移动、删除帧等等。如下演示了这些操作:

图中,我先是添加了Cube的Position属性,然后在0时刻添加了一帧记录起始位置,之后其自动给我创建了一个末尾1s处的帧,我将此帧往后拉了一些,大概在1.3s处,然后调整了Cube的位置,再在中间添加了一帧记录当前Cube的位置,我先是通过鼠标右键添加(添加到鼠标点击处),后来又删除,重新通过添加帧按钮添加的(添加到游标处),至此动画创建结束。可以看到,非录制状态下,帧的添加是要我们自己手动添加的,不过我依然可以通过调整模型来自动记录调整的属性。

如何添加帧

  • 鼠标右键添加:点到哪里添加到哪里,且注意左侧属性,在不同行可以只记录特定属性或属性中的一个值,或者记录全部属性。换言之,我们看到的K帧窗口中的小点,即表示对一个属性的记录,图中,最上面的点是表示所有属性,第二个表示Position属性,再往下则是每个单独的属性x、y、z。这些属性鼠标左键是可以点击选中的。如图:

我是左键选中再操作的,实际可以直接右键操作,不用左键先选中。

  • 鼠标左键双击:和鼠标右键添加一样。

  • 添加按钮:只能在游标位置处添加,且会记录全部属性。

1.2.3 曲线K帧窗口

        点击窗口中的Curves即可切到此窗口。

上方依旧是时间,左侧表示值的变化,不同颜色代表不同属性。在属性值变化的设置上相比于之前的表形式更加灵活一些,毕竟可以调整曲线。其他的跟之前的窗口没太大区别。这里不过多介绍了,想用这种方式的话,上手操作操作基本就熟悉了。

1.3 动画参数窗口

        选中创建的动画文件,即可在Inspector面板中看到相关参数:

1.3.1 Loop Time

        勾选Loop Time表示,播放动画剪辑并在到达结尾时重新开始。勾线后可设置如下属性。

Loop Pose:无缝循环运动。

Cycle Offset:循环动画在其他时间开始时的周期偏移。比如一个动画的进度条是A→B,此时因为我们已经勾选了Loop Time,所以动画进度条可以看成A→B→A,这个参数是则是用于调整动画在A→B→A中的偏移的。假设动作是跳跃动作,A是蹲下,B是浮空,那么通过此参数就可以将整体动画后移,让B变为蹲下,让A就变为浮空,需要注意是整个动画整体上的偏移。如下,用了个比较明显的动作:

可以看到,动画在整个循环进度条中发生了偏移。

1.3.2 Root Transform Rotation

        根转换旋转。PS:首先要理解下根运动的含义,在Animator窗口中有讲到,可以Ctrl+F搜索下,先看下。(先看完根运动含义)这里先提前说下Bake Into Pose,其会将根运动烘焙到Pose中,可以理解为模型姿势,烘焙后根运动的位移之类变化就会应用到模型身上,但仅仅是模型身上,不会对transform里的参数产生影响。演示,Animator窗口不应用根运动(若看根运动定义时没继续往下看完Animator窗口的介绍,就先忽略这点,等会看了就懂了),来查看Bake Into Pose的影响:

可以看到,在未勾选Bake Into Pose时,模型transform未发生位置变化,且动画一直锁定在模型位置不会发生视觉上的位置偏移。而在勾选后,transform依旧不会变化,但动画在视觉上发生了位置偏移,这是因为根运动被烘焙到了姿势当中。

Bake Into Pose(Rotation):将根旋转烘焙到骨骼移动。若在Animator窗口中开启了运用根运动,则勾选此选项会关闭Animator中运用根运动的影响,即动画不会影响模型transfomr中的rotation,应用Bake Into Pose的效果。如图,运用根运动,在勾选Bake Into Pose时模型transform未旋转,然后去掉勾选后就开始控制模型旋转:

Based Upon:根旋转基础。动作朝向。分为Origin和Body Orientation选项。用于控制动画朝向的,前者使用动画文件本身的朝向(一般使用这个),后者是让动画朝向与模型朝向(z轴朝向)一致。如图:

Offset:偏移量。调整动作朝向的偏移量,对上面的Origin和Body Orientation都有效。如下:

1.3.3 Root Transform Position(Y)

  • Bake Into Pose:作用同上。只不过这里是对Y轴的影响。
  • Based Upon:垂直根位置的基础。垂直位置定点。分为Original、Center of Mass、Feet。分别是使用源文件垂直位置,使用质心位置作为垂直位置,使用双脚位置作为垂直位置。具体可以试一试,这里就不演示了。
  • Offset:偏移量。控制垂直位置偏移。

1.3.4 Root Transform Position(XZ)

  • Bake Into Pose:作用同上。只不过这里是对XZ轴(平面移动)的影响。
  • Based Upon:水平根位置的基础。水平位置定点。分为Original、Center of Mass。分别是使用源文件水平位置,使用质心位置作为水平位置。

1.3.5 Mirror

        勾选后讲动画镜像。

1.4 小节

        说实话,我在介绍动画的制作时也只是做了基础的介绍。小细节的东西很多,但又很基础,上手操作尝试几次基本就都知道了,所以这里没有做过多的介绍。各位在学习时,多尝试做几个动画,操作操作也就基本掌握了。

2 动画控制器

动画控制器是用于控制动画的文件,可与代码配合,实现控制动画切换等功能。

2.1 小案例

2.1.1 模型与Animator

        这里用的是Unity Chan模型(什么?你不知道Unity Chan是什么,那你现在知道了,She is my waifu),在资源商店就能找到,不过动画的则是用的其他动画,不是Unity Chan自带的。首先给模型添加一个Animator组件,然后设置如下:

        在讲参数之前首先说一个概念:根运动。

        根运动可以简单理解为动画本身的运动,这里强调的不是动画的动作,而是动画所带来的的如位移、面向旋转、高度变化这类变化。Unity中通过根变换来将角色的质心在Y平面上投影来匹配根运动,因此根运动可应用于Unity中的角色模型上。那么如何运用呢?有两种方式,一种是Animator面板上的Apply Root Motion,还有一种是动画参数窗口中的Bake Into Pose,这个在前面已经讲过了,不过建议看完下面的Apply Root Motion之后再返回上面去看Bake Into Pose。

  • Controller:动画控制器,等会就创建,

  • Avatar:模型骨骼,一般模型都会自带自己的骨骼,这里使用的就是Unity Chan包中自带的。

  • Apply Root Motion:是否使用根运动。若使用根运动,则会将根运动中的位移、面向旋转、高度变化这些应用到角色模型上且会影响角色transform组件当中的数值。但前面说过在动画参数窗口中的Bake Into Pose可以将根运动烘焙到动作中(烘焙到动作中角色也会位移、旋转,但不会影响transform组件的数值),两者都应用了根运动,也就是说两者存在优先级问题。若勾选了Bake Into Pose则以Pose为准,即不会影响transform的值。另外,此Apply Root Motion选项也可以理解为是选择从动画本身还是从脚本来控制角色transform组件的位置和旋转值。

  • Update Mode:此选项可选择Animator何时更新以及应使用哪个时间标度(可以理解为时间速度)。

    • Normal:Animator 与 Update 调用同步更新,Animator 的速度与当前时间标度匹配。如果时间标度变慢,动画将通过减速来匹配。

    • Animate Physics:Animator 与 FixedUpdate 调用同步更新(即,与物理系统步调一致)。如果要对具有物理交互的对象(例如可四处推动刚体对象的角色)的运动进行动画化,应使用此模式。

    • Unscaled Time: Animator 与 Update 调用同步更新,但是 Animator 的速度忽略当前时间标度而不顾一切以 100% 速度进行动画化。此选项可用于以正常速度对 GUI 系统进行动画化,同时将修改的时间标度用于特效或暂停游戏。

  • Culling Mode:为动画选择的剔除模式。

    • Always Animate:始终进行动画化,即使在屏幕外也不要剔除。

    • Cull Update Transforms:未显示渲染器时,禁用变换组件的重定向、IK(反向动力学)和写入。

    • Cull Completely:未显示渲染器时,完全禁用动画。

2.1.2 创建动画控制器

如图,在找个文件夹,在其内创建即可。创建后双击打开动画控制器文件,即可打开Animator窗口。

将一个动画文件拖到Base Layer窗口内,这里我找了一个人物模型的待机动画Idle。

之后将刚刚创建的动画控制器拖拽到Unity Chan身上的Animator组件上。

2.1.3 演示

运行。

可以看到,模型播放了待机动画。

2.2 Animator窗口

        首先,在Animator窗口内各种操作,比如鼠标左键、右键、滚轮、按下滚轮等等,以及什么快捷键之类的就不说了,太基础的东西了,说不完,自己操作操作就什么都懂了。后续内容也同理,个别可能会提下。

  • 动画层级窗口:即左侧窗口,与参数窗口共享一左侧位置,会显示不同的动画层级,不同的动画层级可以实现不同的动画,层级之间可以相互覆盖。可以实现在特定情况下让某一层级动画去覆盖另一层级动画,比如人物普通状态与骑乘坐骑的状态。

  • 动画层级:创建的动画层级,点击即可改变右侧动画窗口。

  • 动画窗口:用于控制各种动画之间的关系。更准确说,窗口内的小方块可以理解为“状态”。

  • 参数窗口:在此窗口内可以自定义参数,程序可借助于这些参数来实现动画切换效果。

2.3 状态参数窗口

        点击动画窗口内的某一个状态(小方块),比如这里点击Idle,在左侧Inspector面板内就会显示各种参数信息,如下:

  • Motion:动画文件。

  • Speed:动画速度。设置为负时,可以倒播。

  • Motion Time:动画执行时间。

  • Mirror:是否镜像动画。只适用于人型动画。

  • Cycle Offset:循环偏移量。

  • Foot IK:脚部IK。【】

  • Write Defaults:动画是否写回默认值。【】

  • Transitions:过渡。不同状态之间可以过渡。

  • Parameter:需要在参数窗口内创建参数后才可使用,可实现相关属性与参数的联动效果。【】

2.4 动画状态机

官方文档解释

        角色或其他动画游戏对象通常具有若干不同的动画,这些动画对应于该角色或对象可在游戏中执行的不同动作。例如,角色可以在空闲时轻微呼吸或摇摆,在得到指令时行走,以及从平台上跌落时恐慌地抬起手臂。一扇门可能具有打开、关闭、卡住和撞开动作的动画。动画系统(Mecanim)使用类似于流程图的可视化布局系统来表示状态机,从而控制需要在角色或对象上使用的动画剪辑并对这些动画剪辑排序。

        嗯....实际就是动画窗口内的东西,各个状态与其之间的连接关系,结合层级、参数等控制,即为动画状态机。动画剪辑就是我们最开始创建的动画Animation。

2.4.1 过渡

        在动画状态机内,宏观来看,其状态(小方块)之间的切换可称之为“状态过渡”。过渡是需要连接箭头的,点击箭头又有很多参数可调整,那么箭头就可以称之为“动画过渡”。

2.4.2 默认状态

        如下图动画窗口,在其中创建了一个新状态,可以发现新状态与Idle状态的颜色是不同的。

这是因为Idle是第一个创建的状态,其为默认状态,其会与Entry自动相连。默认状态是游戏运行时,模型自动播放的状态。若想更改其他状态为默认状态只需要右击想要更改的状态,然后设为默认状态即可,如图:

其他创建的非默认状态想要播放,则需要与默认状态连线或通过参数控制来转换。

2.4.3任何状态

        Any State,表示所有状态。若有一个状态A是所有其他状态都可以直接转过去的,那么就可以将Any State与状态A连接。

2.4.3 动画过渡(连线)

        各状态之间的连线,后面会讲。

2.4.5 控制参数

如图,可用参数有四种,接下来介绍其一般用途。

  • Float:浮点类型。用于大于、小于时,切换状态。

  • Int:整型。用于大于、小于、等于、不等于时,切换状态。

  • Bool:布尔类型,具有持续性。当满足ture或false时,切换状态,在bool值未改变回来时,保持切换后的状态。

  • Trigger:也是布尔,但不具有持续性。true时切换状态(动画),通常用于触发式动画,即触发切换执行完动画后,直接返回原先状态。

那么我们如何使用控制参数呢?

        我们角色目前身上是挂载有一个Animator脚本的,我们需要在脚本中获得此组件来设置以上参数。但是在具体设置前,还需要现在Animator窗口中创建相关参数提供给我们使用。如下图:

在图中我在左侧创建了四个参数(使用旁边那个小+号),并将类型作为参数名,分别对应了四种参数,且面板上的值即为默认值,然后在状态机里(动画窗口,后续就称状态机了)加入了Walk状态,并将Idle与Walk状态相连接(右键状态→Make Transition即可连接状态。选中连线按下Delete可删除),连线即动画过渡。然后选中从Idle→Walk的动画过渡(连线),在Inspector面板中可添加之前创建的参数。

选择某一类型参数后,可设置条件,满足条件即可执行当前的动画过渡。Bool类型可选true、false。Float和Int都是设置超过或低于某一个阈值。Trigger没有可设置内容。这里我们选择使用Bool类型,将Idle→Walk设置为ture,Walk→Idle设置为false。之后创建一个脚本挂载到角色上,我挂载的脚本代码如下:

using UnityEngine;public class ChangeAnimation : MonoBehaviour
{private Animator m_animator;//Animator组件private void Awake(){//获取组件m_animator = this.GetComponent<Animator>();}private void Update(){//按下Q键if (Input.GetKeyDown(KeyCode.Q)){//设置参数Bool为truem_animator.SetBool("Bool", true);}//按下E键if (Input.GetKeyDown(KeyCode.E)){//设置参数Bool为falsem_animator.SetBool("Bool", false);}//m_animator.SetFloat(name, floatValue);    //设置Float类型参数//m_animator.SetInteger(name, intValue);    //设置Int类型参数//m_animator.SetTrigger(name)               //设置Trigger参数,无值,调用此方法即达成动画过渡条件}  
}

之后运行程序按下Q、E测试效果:

可以看到,在按下Q后Bool变量转为ture,状态机切换为Walk状态,模型播放走路动画。在按下E后Bool变量转为false,状态机切换为Idle状态,模型播放待机动画。

2.5 混合树

官方文档解释

        游戏动画中的一项常见任务是在两个或更多相似运动之间进行混合。也许最熟知的示例就是根据角色的速度来混合行走和奔跑动画。另一个示例是角色在奔跑期间转向时向左或向右倾斜。 ​ 区分过渡与混合树十分重要。虽然两者都用于创建平滑动画,但它们用于不同种类的情况。

  • 过渡用于在给定时间内从一个动画状态平滑过渡到另一动画状态。过渡作为动画状态机的一部分指定。如果过渡很快,从一个运动到完全不同运动的过渡通常没有问题。

  • 混合树允许通过不同程度合并多个动画来使动画平滑混合。每个运动对最终效果的影响由一个混合参数控制,该参数只是与 Animator Controller 相关联的数字动画参数之一。为了使混合后的运动合理,要混合的运动必须具有相似的性质和时机。混合树是动画状态机中的一种特殊状态类型。

        例如,类似运动可能是各种行走和奔跑动画。为了使混合取得良好效果,剪辑中的动作必须在标准化时间内的相同点进行。例如,可将行走和奔跑动画对齐,使得脚与地面的接触时刻发生在标准化时间内的相同点(例如,左脚接触点为 0.0,右脚接触点为 0.5)。由于使用标准化时间,因此剪辑长度不同并不要紧。

        总之可以理解为相比于之前的动画过渡,混合树可以实现更加顺滑、更加自由的动画过渡。

2.5.1 创建混合树

  1. 右键单击 Animator Controller 窗口上的空白区域。

  2. 从显示的上下文菜单中,选择 Create State > From New Blend Tree。

  3. 双击混合树 (Blend Tree) 以进入混合树视图 (Blend Tree Graph)。

2.5.2 混合树参数面板

        点击Blend Tree,Inspector中显示内容如下:

Blend Type(混合树类型)

  • 1D:1D模式,只有一个参数控制。

  • 2D Simple Directional:2D模式,有两个参数控制。适合不同方向的动画混合,比如向前、后、左、右,若是前走和前跑就不合适了。在(0,0)位置可以选择放入一个Motion(下面有解释),比如待机状态。PS:在权重图上的具体感觉是,过渡只有在靠近阈值时才会发生快速的动画过渡,远离阈值时,在较大阈值范围内都是混合动状态。

  • 2D Freeform Directional:2D模式,有两个参数控制。适合方向不同的动画混合,也适合同方向的混合。在(0,0)位置应该有一个Motion,比如待机。PS:在权重图上看,若两个Motion在权重图上是相对于原点直线,则在以直线切换经过原点并且原点(0,0)处无动作时,状态会发生较为僵硬快速的变化,看起来没有过渡而是直接切换了动作,所以需要在原点处加上一个Motion作为过渡,通常设置为待机动作。

  • 2D Freeform Cartesian:2D模式,有两个参数控制。适合两个参数不是全都是表示方向时的动画混合。意思就是我们是2D嘛,所以有两个参数嘛,通常这两个参数分别表示前后方向和左右方向,现在就是不全表示方向,保留前后方向参数,另外一个参数改成别的,比如角速度,来实现往前跑转弯效果,这时一个参数是方向,另一个是角速度,满足“两个参数不是全都是表示方向”,此时便适合用这个类型。

  • Direct:直接混合。可以直接控制每个节点的权重,之前的都是权重分配都会在靠近一个Motion时,削减其他Motion的权重,而这个则是无视这个情况,比如两个Motion都是设置为权重1(此模式权重范围0-1),那么就是两个Motion权重都是1而不是各自0.5。适合于面部表情之类的。

PS:这几个2D概念说这么多还是模糊,实际还是要在具体使用中多尝试看看区别才行,这样才能更好的理解。

Parameter(参数)

        即Animator面板中创建的参数。可选择创建参数中的Float类型参数。若无Float类型参数,则在混合树被创建时自动创建一个Float类型的Blend参数。

Motion(动作)

        可以是动画或是子级混合树。点击加减号操作,或是右键混合树视图中的Blend Tree操作。

Blend Type详细说明

Blend Type 1D:

        在我加入动作后,窗口内容会发生变化。

        首先看动画列表,由左往右是动画、阈值、动画速度(时间缩放)、动画是否镜像。这里特别说下阈值,当Parameter的值为对应Motion的阈值时,此为Motion运行100%时候的值,因为是混合树,所以Motion的运行大多数都是混合的,所以运行时不同Motion占有不同的比例权重,100%可以理解为完全在运行当前Motion,其他Motion没有与其混合运行。然后上方会显示一个蓝色的图像,y轴是权重占比,x轴是Parameter值(范围是阈值的范围),图中每个三角都是一个Motion,表示所有Motion在不同Parameter值下的权重占比。

        同时下方也出现了新参数。Automate Thresholds是自动阈值的意思,勾选后我们无法自己设置阈值,其会根据动画的加入自动调整。当我将其去掉勾选后便可以自己调整了,且会出现新的参数。

Compute Thresholds,计算阈值,即提供的几种阈值计算方法,选择后会自动应用到阈值上。

Adjust Time Scale,调整时间缩放,也是提供的几种时间缩放方法,可选择使用。 可以看一下混合动画的效果:

Blend Type 2D:

        以2D Freeform Directional为例。2D是需要两个Float类型参数的,这里设置为Blend1和Blend2,并将加入Walk和Run动画Motion,之后权重图如下:

首先权重图是一个x、y轴组成的二维坐标系。图中两个蓝点是Motion 100%权重位,红点是Blend1和Blend2组成点(x,y),Blend1表x值,Blend2表y值。当红点靠近蓝点时,蓝点Motion的混合权重就会增大。下方Motion列表中增加了PosX、PosY,其用于设置Motion蓝点在权重图中的位置,x、y轴的值没有范围限制,可任意设置。

        这里再多增加几个Motion,加入待机、前走、后退、左走、右走、前跑、后退跑、左跑、右跑。此时权重图如下:

然后可以看下混合效果:

2.6 子动画状态机

        子状态机和状态机是基本一样的,只是套娃关系,但当然还是有一些小区别的。

2.6.1 创建子状态机

        在状态机内鼠标右键,Create Sub-State Machine。

2.6.2 子状态机与其他状态机的联系

        左键双击创建的子状态机后即可而进入子状态机内,如下:

基本一样,特别注意(Up)Base Layer,其表示当前状态机的上层状态机(所有上层)。我先加入一个状态,再将加入状态连接到(Up)Base Layer,如下:

当我连接后出现了两种选项,第一个是其他状态,即上层中的所有状态都会给你列出来,包括上层的子状态机的,选择状态就会在上层当前子状态机拉一条线连接到选择的状态;第二个是状态机,若是选择状态机,则默认是从所选状态机的Entry来切换状态。

2.6.3 Exit状态

        若是最终连接到Exit来退出,那么会回到上一层,若在上层子状态机有连线到其他地方且满足条件,则走此路线,若不满足或无连线则从Entry进入。

        PS:但我用起来感觉有时候改变参数状态机却没生效,这种情况发生在使用状态机去连接的情况,这时候线是灰色的,若是从子状态机内直接连接外面的状态,则是白色的线,就不会出现这种情况。另外,Entry是连接到默认状态的,前面说了不满足条件的话会从Entry进入然后到默认状态,但若状态机本身有条线连接到默认状态,那么无论次连线条件是否满足,都会走这条线,就结果来看没有变化,都是执行默认状态。

2.7 重写动画控制器

        若我们已经实现了一套动画控制器,这时候我们想在原先动画控制器的基础上替换一套动画,即仅仅替换动画,而其他的所有设置都不改变,比如不同职业间的动作状态过渡是相同的设计,但只是动画不同,那我们就只需替换一套动画即可。此时便可以使用“重写动画控制器”。创建如下:

创建后,选中动画控制器,Inspector面板如下:

Controller即要重写的控制器,把之前的控制器拖入:

可以替换的动画就会被显示到下方,只需要将新动画拖入对应位置即可,若没有拖入新动画则使用原控制器的动画。

        之后只需要将重写动画控制器替换角色Animator组件上的原控制器,即可使用新一套动画了。

3 动画事件

        动画剪辑的事件。我们可以在动画剪辑中添加事件,进而可以在动画的特定位置执行处理函数。比如在动作做到一半时触发特效什么的。

3.1 添加动画事件

        需要在Animation窗口中添加动画事件,如图:

添加后就会出现一个小图标表示这里有事件,点击可在Inspector面板中看到Animation Event的参数设置,这里可以选择处理函数。(注意这里我把事件添加到了动画大概中间的位置)

那么如何选择我们自定义的方法呢?

3.2 提供处理方法

        首先看这个动画剪辑处于哪个游戏对象身上,这里我添加的动画剪辑是在Cube身上,具体关系是:Cube对象→Animator组件→Cube动画控制器→动画剪辑。如图:

Cube动画控制器中:

        那么在找到是属于哪个游戏对象后,那么只需要在挂载在此对象身上的脚本中添加公共方法即可,这些公共方法是可以在刚才的Inspector面板中识别并选择的。这里我添加了一个Cube.cs脚本挂载到Cube对象身上,代码如下:

using UnityEngine;public class Cube : MonoBehaviour
{public void AnimationEventTest(){Debug.Log("触发动画事件!");}
}

之后我们再去点击Animation窗口中的事件标志,在Inspector面板中的Animation Event的参数设置中发现此时可以选择代码中的函数。

选择函数后运行程序,会发现在动画播放到大概中间的位置时,控制台将输出内容。

3.3 演示

3.4 更详细的Animation Event参数设置

3.4.1 参数设置

        刚刚我们看到Animation Event参数设置中只有一个方法参数,但是当我们选中动画剪辑的原始文件,再次点击事件标志时,将看到更相机的Animation Event参数设置,如下:

可以看到可设置的参数有5个,第一个是Function,表示选择的处理函数,后面多出来的四个参数则是提供给处理函数使用的,我们可以先在这里设置好参数值,之后在处理函数中可使用这些值。

  1. Function:处理方法。

  2. Float:float类型参数。

  3. Int:int类型参数。

  4. String:string类型参数。

  5. Object:Object类型参数(注意O是大写)。Object作为祖先类意味着这里可以传递的对象的类型很自由,在函数中使用时需要注意把类型转换为传递对象的原始类型。比如传递的对象是A类型,那么在函数中就需要转为A类型。

PS:点击游戏对象再点击事件标识,就可以看到简化的Animation Event参数设置。若处理函数传递了“参数”,则简化后的参数设置中也会显示“参数”。

3.4.2 函数传参

        将参数传递给函数,进而提供给函数使用。传给函数的参数只能有一个。传参的方式可以分为两种:

  • 传递单个参数

  • 传递所有参数

具体使用哪种,是在定义处理函数时决定的。

传递单个参数的例子:

using UnityEngine;public class Cube : MonoBehaviour
{//只能传递一个参数//传递int类型参数,变量名随意,也可以换成其他设置类型public void AnimationEventTest(int num){Debug.Log("触发动画事件!" + num);}
}

传递所有参数的例子:

using UnityEngine;public class Cube : MonoBehaviour
{//只能传递一个参数//传递一个AnimationEvent类型,变量名随意,内部包含所有参数public void AnimationEventTest(AnimationEvent allPamams){Debug.Log("float类型参数:" + allPamams.floatParameter);Debug.Log("int类型参数:" + allPamams.intParameter);Debug.Log("string类型参数:" + allPamams.stringParameter);Debug.Log("Object类型参数:" + allPamams.objectReferenceParameter);//真实使用场景别忘了根据需要转换类型Debug.Log("处理函数名:" + allPamams.functionName);}
}

4 后记

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

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

相关文章

C++二级指针的用法指向指针的指针(多级间接寻址)

指向指针的指针是一种多级间接寻址的形式&#xff0c;或者说是一个指针链。 指针的指针就是将指针的地址存放在另一个指针里面。 通常&#xff0c;一个指针包含一个变量的地址。当我们定义一个指向指针的指针时&#xff0c;第一个指针包含了第二个指针的地址&#xff0c;第二个…

【格与代数系统】示例

【格与代数系统】格与代数系统汇总 例1 设是由诱导的代数系统&#xff0c;则其上的二元运算满足&#xff08;ABCD&#xff09; A. B. C. D. 代数系统满足交换律、幂等律、吸收律、结合律 例2 是&#xff08;ABCD&#xff09; A.有界格 有界格&#xff1a;有最大、最小元…

Stable Diffusion 项目实战落地:手机壁纸制作-第一篇 从零基础到生成艺术品的第一步!

大家好!欢迎来到《StableDiffusion实战-手机壁纸制作》系列的第一篇! 在这一篇文章里,我们将一起探索如何用StableDiffusion(SD)这款强大的工具,快速制作出炫酷的手机壁纸。 如果你对生成艺术、AI绘图感兴趣,那你一定不能错过! 你能做什么?你将做什么! 在之前的系…

WEB3开启 Hardhat 自动验证有什么意义

这是个非常好的问题&#xff0c;尤其是你在学习 Web3 后端开发时&#xff0c;理解为什么要启用 Hardhat 自动验证合约源码&#xff0c;会让你开发流程更完整、更专业。 ✅ 一句话总结&#xff1a; 开启 Hardhat 自动验证的意义是&#xff1a;让你的合约在区块链浏览器&#xff…

Qt窗⼝的学习(一)

Qt窗⼝是通过QMainWindow类来实现的。 QMainWindow是⼀个为⽤⼾提供主窗⼝程序的类&#xff0c;继承⾃QWidget类&#xff0c;并且提供了⼀个预定义的 布局。QMainWindow包含⼀个菜单栏&#xff08;menubar&#xff09;、多个⼯具栏(toolbars)、多个浮动窗⼝&#xff08;铆 接部…

C++ 面试题常用总结 详解(满足c++ 岗位必备,不定时更新)

&#x1f4da; 本文主要总结了一些常见的C面试题&#xff0c;主要涉及到语法基础、STL标准库、内存相关、类相关和其他辅助技能&#xff0c;掌握这些内容&#xff0c;基本上就满足C的岗位技能&#xff08;红色标记为重点内容&#xff09;&#xff0c;欢迎大家前来学习指正&…

git提交的脚本无执行权限怎么办

问题描述 自己写的小项目&#xff0c;没有在服务器安装 Jenkins 进行项目部署&#xff0c;为了图方便&#xff0c;在项目中编写了一个 deploy.sh 脚本文件用来执行项目部署。但是在服务器上 pull 下来之后发现脚本文件没有执行权限&#xff0c;通过 chmod 命令进行赋权&#x…

004.chromium编译进阶-启动时传入cookies

一、目标&#xff1a; 实现传入参数--set-cookies[{"domain":"https://baidu.com","name":"AAAA","value":"111"},{"domain":"https://baidu.com","name":"BBB","…

【数据库复习】

数据库复习题 一、填空题1&#xff0e;数据库系统一般由&#xff08;数据库&#xff09;、应用系统、&#xff08;数据库管理系统&#xff09;、&#xff08;数据库管理员&#xff09;和用户构成。2&#xff0e;数据模型通常由&#xff08;数据结构&#xff09;、&#xff08;数…

微信小程序:选择页面单选实现(多页面均可选择)

一、效果展示 1、主页面 展示了两个选择行 2、选择页面 根据传递的参数决定员工展示的数据,并且单选,可将数据传递给主页面 二、主页面实现 1、视图层 写入了采购员和库管员的行选择信息 <view class="item flex flex-between"><view class="i…

使用docker-compose搭建redis-cluster集群

前言 如果你也因为centos的gcc版本落后导致redis编译安装不通过而烦恼&#xff0c;大可以试一试用docker去搭建redis集群。本文以单节点搭建redis-cluster三主三从为例。 ip&#xff1a;192.168.0.10redis信息&#xff1a; 客户端连接端口&#xff1a;7001 -7006集群间通信端…

【LLaMA-Factory 实战系列】二、WebUI 篇 - Qwen2.5-VL 多模态模型 LoRA 微调保姆级教程

【LLaMA-Factory 实战系列】二、WebUI 篇 - Qwen2.5-VL 多模态模型 LoRA 微调保姆级教程 1. 引言1.1 为什么选择 Qwen2.5-VL-3B-Instruct&#xff1f;1.2 环境要求 2. 环境搭建2.1 安装 LLaMA-Factory2.2 验证安装 3. 数据集准备与配置3.1 数据集结构3.2 数据格式3.3 数据集声明…

风险矩阵与灰色综合评价

一、风险矩阵&#xff08;Risk Matrix&#xff09; 1. 定义与原理 定义&#xff1a;风险矩阵是一种通过二维网格&#xff08;可能性 vs. 后果严重程度&#xff09;可视化展示风险等级的工具&#xff0c;用于优先级排序和决策支持。核心要素&#xff1a; 横轴&#xff08;X轴&…

谷歌浏览器电脑版官方下载- Google Chrome官方网页版入口

谷歌浏览器&#xff08;Google Chrome&#xff09;是一款由谷歌公司开发的免费网页浏览器&#xff0c;自2008年首次发布以来&#xff0c;迅速成为全球最受欢迎的浏览器之一。它以简洁的界面设计、快速的浏览速度和强大的安全性能而闻名。谷歌浏览器支持多种操作系统&#xff0c…

垂直电商供应链平台:重构产业生态,驱动数字化增长

垂直电商供应链平台&#xff1a;重构产业生态&#xff0c;驱动数字化增长 在电商行业竞争日益激烈的当下&#xff0c;垂直电商供应链平台凭借对细分领域的深度聚焦与数字化能力&#xff0c;成为产业升级的关键引擎。本文围绕垂直电商供应链平台的架构、价值及生态构建展开&…

VSCode 插件 Remote - SSH:开启高效远程开发之旅

在当今的软件开发领域&#xff0c;远程开发已经成为了一种越来越流行的工作方式。无论是分布式团队协作&#xff0c;还是需要在不同环境中进行开发&#xff0c;远程开发都能为开发者带来极大的便利。而 VSCode 的 Remote - SSH 插件&#xff0c;就是一款能够帮助开发者实现高效…

亚矩阵云手机+Whatnot:直播电商的自动化增长引擎

在直播电商蓬勃发展的今天&#xff0c;Whatnot作为北美领先的收藏品和潮流商品拍卖平台&#xff0c;吸引了大量卖家和收藏爱好者。然而&#xff0c;高效运营多个账号、管理直播场次、优化出价策略等挑战&#xff0c;让许多商家难以规模化经营。​​亚矩阵云手机​​与​​Whatn…

关于vue.mixin与vue.use的用法分析

背景。源码不会读&#xff0c;不清楚的问大模型。特别是对平常开发太会用到的情形。 vue.mixin。是将每一个页面注入mixin的内容。会对页面中注入$uStore而不是方便获取状态信息。 vue.use。按装的插件。用于封装完整的功能&#xff0c;如UI库&#xff0c;路由拦截器等&…

MySQL 8.x配置MGR高可用+ProxySQL读写分离(二):ProxySQL配置MySQL代理及读写分离

#作者&#xff1a;stackofumbrella 文章目录 ProxySQL简介ProxySQL架构ProxySQL的安装与配置在不同层次间移动配置 ProxySQL简介 ProxySQL是基于MySQL的一款开源的中间件的产品&#xff0c;是一个灵活的MySQL代理层&#xff0c;可以实现读写分离&#xff0c;支持Query路由功能…

基于 Python Flask 的 B/S 架构项目的软件设计思路

文章目录 基于 Python Flask 的 B/S 架构项目的软件设计思路1. 引言2. B/S架构概述2.1 什么是B/S架构2.2 B/S架构的组成层次2.3 B/S vs C/S架构对比2.4 现代B/S架构的发展趋势 3. Flask在B/S架构中的定位3.1 Flask作为B/S架构的后端框架3.2 Flask的架构优势3.3 Flask在不同B/S架…