目标:给角色添加动画
动画类的结构关系
1.创建类
2.创建子类
3.编译,再重新启动UE编辑器
创建英雄动画实例
4.写代码:
(1)WarriorCharacterAnimInstance.h:
// Copyright @ ChenChao
#pragma once
#include "CoreMinimal.h"
#include "AnimInstances/WarriorBaseAnimInstance.h"
#include "WarriorCharacterAnimInstance.generated.h"
class UCharacterMovementComponent;
class AWarriorBaseCharacter;
/**
*
*/
UCLASS()
class WARRIOR_API UWarriorCharacterAnimInstance : public UWarriorBaseAnimInstance
{
GENERATED_BODY()
public:
//原生初始化动画
virtual void NativeInitializeAnimation() override;
//原生线程安全更新动画
virtual void NativeThreadSafeUpdateAnimation(float DeltaSeconds) override;
protected:
//所属角色
UPROPERTY()
AWarriorBaseCharacter* OwningCharacter;
//所属角色移动组件
UPROPERTY()
UCharacterMovementComponent* OwningMovementComponent;
// 地面速度
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "AnimData|LocomotionData")
float GroundSpeed;
//是否有加速度?
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "AnimData|LocomotionData")
bool bHasAcceleration;
};
(2)实现初始化动画方法:
//原生初始化动画
void UWarriorCharacterAnimInstance::NativeInitializeAnimation()
{
Super::NativeInitializeAnimation();
//给所属角色赋值
OwningCharacter = Cast<AWarriorBaseCharacter>(TryGetPawnOwner());
if (OwningCharacter)
{
//赋值移动组件
OwningMovementComponent = OwningCharacter->GetCharacterMovement();
}
}
这段代码是Unreal Engine中角色动画实例类的初始化函数实现,主要功能是获取并绑定角色及其移动组件。具体分析如下:
函数继承关系:
- 通过
Super::NativeInitializeAnimation()
调用父类初始化逻辑 - 属于
UWarriorCharacterAnimInstance
动画实例类
核心功能实现:
- 使用
TryGetPawnOwner()
获取动画实例所属的Pawn对象 - 通过
Cast<AWarriorBaseCharacter>
转换为自定义角色基类 - 成功获取角色后,再获取其移动组件
CharacterMovement
典型应用场景:
- UE5角色动画系统中初始化动画相关属性
- 常用于获取角色状态信息用于动画蓝图混合
- 与CharacterMovement组件配合实现移动动画效果
安全注意事项:
- 使用
Cast
进行安全类型转换 - 对指针有效性进行检查(if(OwningCharacter))
- 避免在未初始化状态下访问移动组件
(3)原生线程安全更新动画
//原生线程安全更新动画
void UWarriorCharacterAnimInstance::NativeThreadSafeUpdateAnimation(float DeltaSeconds)
{
Super::NativeThreadSafeUpdateAnimation(DeltaSeconds);
if (!OwningCharacter || !OwningMovementComponent) return; //安全检查
//地面速度
GroundSpeed = OwningCharacter->GetVelocity().Size2D();
//是否有加速度?
bHasAcceleration = OwningMovementComponent->GetCurrentAcceleration().SizeSquared2D() > 0.f;
}
这段代码是Unreal Engine中动画实例类的线程安全更新函数实现,主要用于实时计算角色移动相关动画参数。以下是关键点分析:
线程安全特性:
- 通过
NativeThreadSafeUpdateAnimation
在工作线程执行动画计算,避免阻塞游戏线程 - 继承父类逻辑后执行自定义更新逻辑(
Super::NativeThreadSafeUpdateAnimation
)
核心功能实现:
- 安全检查确保角色和移动组件有效(
if(!OwningCharacter...)
) - 计算地面速度(
GetVelocity().Size2D()
获取水平速度模长) - 判断加速度状态(
SizeSquared2D() > 0.f
优化性能避免开方运算)
典型应用场景:
- 与
NativeInitializeAnimation
配合实现动画数据初始化+更新的完整流程 - 常用于角色移动动画混合(如走/跑状态切换)
- 通过蓝图暴露变量驱动动画状态机
性能优化点:
- 使用线程安全函数避免主线程竞争
- 采用
SizeSquared2D()
代替Size2D()
减少计算量 - 提前进行空指针检查保证稳定性
bHasAcceleration = OwningMovementComponent->GetCurrentAcceleration().SizeSquared2D() > 0.f;
这段代码是虚幻引擎中用于检测移动组件当前是否有加速度的逻辑判断:
-
代码解析:
OwningMovementComponent
指向拥有该逻辑的移动组件对象GetCurrentAcceleration()
获取当前帧的加速度向量SizeSquared2D()
计算XY平面加速度向量的平方长度(比直接计算长度更高效)- 最终判断结果存入布尔变量
bHasAcceleration
-
性能优化:
使用平方长度比较(> 0.f
)而非实际长度计算,避免了开平方运算,这是游戏开发中常见的优化手段 -
典型应用场景:
- 角色移动状态检测(如判断是否从静止转为移动)
- 动画蓝图中的移动状态切换条件
- 物理模拟中的运动状态判断
-
注意事项:
该判断不考虑Z轴(垂直方向)加速度,如需三维检测应使用SizeSquared()
方法
源代码:
WarriorCharacterAnimInstance.cpp:
// Copyright @ ChenChao
#include "AnimInstances/WarriorCharacterAnimInstance.h"
#include "Characters/WarriorBaseCharacter.h"
#include "GameFramework/CharacterMovementComponent.h"
//原生初始化动画
void UWarriorCharacterAnimInstance::NativeInitializeAnimation()
{
Super::NativeInitializeAnimation();
//给所属角色赋值
OwningCharacter = Cast<AWarriorBaseCharacter>(TryGetPawnOwner());
if (OwningCharacter)
{
//赋值移动组件
OwningMovementComponent = OwningCharacter->GetCharacterMovement();
}
}
//原生线程安全更新动画
void UWarriorCharacterAnimInstance::NativeThreadSafeUpdateAnimation(float DeltaSeconds)
{
Super::NativeThreadSafeUpdateAnimation(DeltaSeconds);
if (!OwningCharacter || !OwningMovementComponent) return; //安全检查
//地面速度
GroundSpeed = OwningCharacter->GetVelocity().Size2D();
//是否有加速度?
bHasAcceleration = OwningMovementComponent->GetCurrentAcceleration().SizeSquared2D() > 0.f;
}
5.编译,运行UE编辑器,创建蓝图子类:
效果: