阿赵UE学习笔记——25、动画状态机播放

本文介绍了如何在虚幻引擎中使用动画蓝图和状态机控制角色动画播放,包括创建状态、指定动画片段、设置状态间切换条件以及利用导管优化复杂的过渡逻辑。

阿赵UE学习笔记目录
  大家好,我是阿赵。
  继续学习虚幻引擎的使用。之前学习了用蓝图直接控制骨骼动画或者蒙太奇动画的播放。这次学习一下通过状态机来控制动画播放。如果熟悉Unity引擎使用的朋友,看到这个状态机应该会觉得很熟悉,因为Unity引擎也有。不过UE的状态机操作起来稍微和Unity有点不一样。

一、动画蓝图

  动画蓝图在前几篇里面和角色蓝图一起学习过。这里回忆一下:
在这里插入图片描述

  双击打开动画蓝图,会看到有一个Output Pose节点,然后我们新建一个State Machine状态机节点,把状态机的输出连到Output Pose节点。
在这里插入图片描述

二、动画状态机

1、创建状态

  接下来双击打开状态机节点:
在这里插入图片描述

  鼠标右键——添加状态,添加一个idle的状态,然后把Entry节点连到idle节点。

2、给状态节点指定动画片段:

双击状态节点:
在这里插入图片描述

  进入到节点编辑界面之后,从资产浏览器拖一个动画进来,然后连接到Output Animation Pose
在这里插入图片描述

  这样就已经为这个状态指定动作了。
  做完了这些操作之后,我们已经拥有了一个状态机,里面有一个idle状态,idle状态里面有一个我们指定的动画。

三、多个状态节点的连接

  接下来我们先创建多几个状态,并为状态指定好动作:
在这里插入图片描述

  比如我这里除了idle以外,还创建了walk走路、jump跳跃、death死亡,这几个状态。从idle状态连接到其他状态,只需要在状态的边缘按下鼠标左键拖出箭头,然后在下一个状态节点上松开鼠标左键就行。
在这里插入图片描述

  拖完之后,会是这样:
在这里插入图片描述

  接下来需要编辑状态与状态之间的切换条件,和Unity的操作有点类似,我先创建了几个变量:
在这里插入图片描述

  注意一下变量是否为公有。这些变量如果是公有,则可以在动画蓝图外部直接访问和修改。如果不是公有,就不能从外部访问,只能从事件图表里面获取外部的变量来设置值了。
在这里插入图片描述

  这里我设置了一个浮点型的变量moveSpeed,一个布尔型的变量isAlive,另一个布尔型的变量isJump。
  接下来,找到idle到walk的这个过渡条件,然后双击:
在这里插入图片描述

  进入到这个过渡规则编辑界面,这里的Result指的是达到什么条件之后,这个过渡是成立的。
在这里插入图片描述

  把moveSpeed变量拖进来,选择获取moveSpeed
在这里插入图片描述

  然后拖出一个大于节点,最后连到Result。这里表达的意思是,当moveSpeed大于0的时候,可以从idle过渡到walk:
在这里插入图片描述

  回到状态机界面,这次双击walk到idle的过渡规则:
在这里插入图片描述

  和上面的操作类似,这次的条件是MoveSpeed小于等于0,则可以过渡。
在这里插入图片描述

  同样的道理操作剩下的节点过渡规则:
从idle到jump的规则是isJump等于true
在这里插入图片描述

从jump到idle的规则是isJump不等于true
在这里插入图片描述

从idle到death的规则是isAlive不等于true
在这里插入图片描述

从death到idle的条件是isAlive等于true
在这里插入图片描述

  编辑完成之后,就可以来测试预览了:
在这里插入图片描述

  在右下角有一个动画预览编辑器,可以通过修改刚才的变量,来测试各个节点之间的动画效果

四、根据时间过渡

  刚才那个例子里面,死亡倒地之后,又复活,人会突然蹦起来,没有一个站立起来的动作过程。所以我这里加了一个standUp的节点。从death到standUp的规则依然是isAlive为true
在这里插入图片描述

  然后standUp到idle的规则,就要改一下,搜索剩余时间,会看到有2个Time Remaining节点可以用,一个是按绝对时间,一个是按百分比:
在这里插入图片描述

  我选择了按百分比的节点,然后连一个小于等于0.1给他,意思就是,当站立的动作播放到剩余不到0.1的时候,就可以过渡到idle节点了。
在这里插入图片描述

  这样设置了之后,当isAlive变为true,角色会先播放一个站立动作,然后回到idle。

五、导管

  除了状态节点以外,还可以创建一种叫做导管的节点
在这里插入图片描述

  导管的图标和状态节点是不一样的。
在这里插入图片描述

  双击进去导管节点,会看到里面和过渡规则编辑是一模一样的。
在这里插入图片描述

  这里就很好理解了,导管其实就是一个过渡规则,如果状态与状态之间的连线规则过于复杂,可以在其中加入导管,增加过渡条件的管理规则。
  另外一种做法是,把所有节点的时间完成后,都连接到导管,然后导管再根据条件,连接到各个状态。大概是这个样子:
在这里插入图片描述

参考的引用内容中未提及在UE5中播放蒙太奇后重设动画蓝图状态机状态的方法。不过结合UE5的常规操作逻辑,一般可以通过以下思路来实现: ### 利用事件通知 在蒙太奇中设置事件通知,当蒙太奇播放到特定位置触发该通知。在事件通知的响应函数里编写代码来重设状态机的状态。比如在蓝图中,可以在动画蓝图或者角色蓝图里创建一个自定义事件,然后在事件通知响应时调用该自定义事件,在自定义事件中修改状态机的状态变量。 ### 蒙太奇播放完成回调 在播放蒙太奇时设置播放完成的回调函数。当蒙太奇播放完成时,调用该回调函数,在函数中重设状态机的状态。在C++代码中可以通过绑定委托的方式实现回调,在蓝图中可以使用蒙太奇播放节点的完成输出引脚连接到相应的节点来处理状态重设。 ### 示例代码(C++) ```cpp // 假设这是一个角色类的头文件 #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "MyCharacter.generated.h" UCLASS() class YOURPROJECT_API AMyCharacter : public ACharacter { GENERATED_BODY() public: AMyCharacter(); // 播放蒙太奇的函数 UFUNCTION(BlueprintCallable, Category = "Animation") void PlayMyMontage(class UAnimMontage* MontageToPlay); // 蒙太奇播放完成的回调函数 UFUNCTION() void OnMontageEnded(UAnimMontage* Montage, bool bInterrupted); protected: virtual void BeginPlay() override; private: // 状态机状态变量 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Animation", meta = (AllowPrivateAccess = "true")) FName CurrentState; }; ``` ```cpp // 角色类的源文件 #include "MyCharacter.h" #include "Animation/AnimInstance.h" AMyCharacter::AMyCharacter() { PrimaryActorTick.bCanEverTick = true; } void AMyCharacter::BeginPlay() { Super::BeginPlay(); } void AMyCharacter::PlayMyMontage(class UAnimMontage* MontageToPlay) { UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); if (AnimInstance && MontageToPlay) { AnimInstance->Montage_Play(MontageToPlay); AnimInstance->Montage_SetEndDelegate(FMontageEndedDelegate::CreateUObject(this, &AMyCharacter::OnMontageEnded), MontageToPlay); } } void AMyCharacter::OnMontageEnded(UAnimMontage* Montage, bool bInterrupted) { // 重设状态机状态 CurrentState = "Idle"; // 可以在这里添加更多的状态重设逻辑 } ``` ### 示例蓝图操作 在蓝图中,从角色蓝图或者动画蓝图中找到播放蒙太奇的节点,连接其完成输出引脚到一个自定义事件,在自定义事件中修改状态机的状态变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值