【AdvancedLocomotionSystemV】第四篇 C++ 实现角色跑步旋转和原地旋转

本文详细介绍了在Unity3D中如何通过自定义Animation Modifier蓝图实现角色的任意角度旋转。关键步骤包括创建并重载OnApply和OnRevert函数以生成和应用旋转曲线,计算旋转值的缩放量,以及监听曲线变化实时更新角色旋转。此外,还讨论了如何通过状态机调整曲线以实现平滑的旋转效果。
摘要由CSDN通过智能技术生成

效果展示

请添加图片描述

查看所有文章

AdvancedLocomotionSystemV

项目地址

Gitee

项目实现思维导图

请添加图片描述
这个地方主要就是在于动画的播放和人物的旋转值进行的匹配。
通过控制动画播放的速率来控制动画播放的时间,然后角色模块收到曲线值的通知进行旋转。
动画是根运动的动画,如果不改变角色移动的旋转值,那么角色就会在原朝向播放动画。

Rotation Amout曲线的实现

创建蓝图,继承Animation Modifier类,里面有两个函数可以进行重载。
一个是On Apply函数,主要作用是用来应用,对动画序列做出一些修改。
另一个是On Revert函数, 进行恢复的操作,恢复对动画序列做出的修改。
可以理解为Do和Undo的作用。

在生成旋转值曲线的时候,我们只需要生成动画曲线,没有其他的改变,所以只要重载On Apply函数即可。

函数实现逻辑很简单。

  1. 检查在生成这个曲线之前有没有该曲线,如果有,进行删除。
  2. 生成新曲线,此时曲线就是一个值为0的直线。
  3. 循环遍历每一帧,计算实际当前帧的旋转值与下一帧的旋转值的差值并添加到曲线中。
  4. 对动画序列进行应用。

具体实现可以在下面的文件夹中找到。
在这里插入图片描述
打开旋转的动画,进行生成曲线操作。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

如何实现任意角度旋转?

如果使用的是同一个动画,不管旋转多少度,他们所花费的时间是一样的。
也就是说旋转的任意角度只会影响到角色旋转。

  • 计算出旋转值的缩放量,因为动画时间是一样的,所以需要对曲线的值进行调整,旋转的角度和动画播放的角度会形成一个比例,那么近似的来看,实际曲线的取值和动画播放的取值也会形成一个比例:
// 步骤4: 计算旋转的缩放量 缩放量无单位,只是旋转值的倍数关系。
if (TargetTurnAsset.bScaleTurnAngle)
{
	// 旋转值的缩放量  = 要旋转的角度 ÷ 动画播放的角度 × 旋转速率 × 动画播放速率缩放值
	//                   =          角度比例 × 旋转速率 × 动画播放速率缩放值
	RotationScale = TurnAngle / TargetTurnAsset.AnimatedAngle * TargetTurnAsset.PlayRate * PlayRateScale;
}
else
{
	// UE_LOG(LogTemp, Warning, TEXT("开启"));
	// 因为这个状态没有开启任意角度旋转,而是使用动画原本的角度,所以角度比例就是 1
	// 所以 旋转的缩放量  = 旋转速率 × 动画播放速率缩放值
	RotationScale = TargetTurnAsset.PlayRate * PlayRateScale;
}
  • 通过状态机更改曲线的方式对曲线进行缩放处理

在这里插入图片描述

  • 角色监听曲线的变化,一旦曲线有值并且可以使用动画过渡,就对角色进行旋转处理。
// RotationAmount曲线中取出来的值CurrentSecondRotation代表的是当前时间(s)的旋转旋转差值。 
// 可理解为 旋转度每秒
const float CurrentSecondRotation = GetAnimCurveValue(TEXT("RotationAmount"));
if (FMath::Abs(CurrentSecondRotation) > 0.001)
{
	/*
	 * AddActorWorldRotation 就是在原基础上添加一个Rotation的值,
	 * 这个添加是一次性的,也没有过渡的过程,一步到位。
	 * 如果没有乘倍数,旋转的值会很大,为什么?
	 * 因为没有乘以倍数的话,那么添加的值就会等于  1 s * CurrentSecondRotation。
	 * 实际上 GetWorld()->DeltaTimeSeconds是比1s小很多的,
	 * 再加上浮点计算有精度丢失的情况,那么就会导致最终累加起来的值和我们想要的值相差很大,
	 * 所以需要乘以一个值来减少他的误差。
	 */
	AddActorWorldRotation(FRotator(0.f, GetWorld()->DeltaTimeSeconds * 30.f
	 * CurrentSecondRotation, 0.f));
	TargetRotation = GetActorRotation();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值