• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

逍遥流

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

UE4 Advanced Locomotion System V3插件 角色的控制分析,关键动画逻辑分析

Advanced Locomotion System V3是一个主角动作“真实感”很强的一个工程,需要学习借鉴。

本文对UE4的一个动作demo的主体结构分析,以及对我们关注的关键动画逻辑的分析
https://www.unrealengine.com/marketplace/advanced-locomotion-system-v1

1 Advanced Locomotion System V3主体结构分析

本文重点关注的是角色的控制和动作,所以会跳过无关的模块。

1.1 player基类关系分析

分析方法:
在“世界大纲视图”,搜到MannequinCharacter_Player,点击右侧的<编辑MannequinCharacter>,会弹出来一个类默认值窗口,点击上方蓝色的“打开完整的蓝图编辑器”,即可查看当前类的蓝图,点击工具栏的“类设置”,在细节窗口可以更改此类的父类,查看此类继承的接口。在当前类的蓝图的右上角,可以查看父类,此例中,MannequinCharacter的父类为ALS Base Character;使用类似的方法,可以看到ALS Base Character的父类是Character,至于Character的父类就需要查看unreal的文档或unreal源码了。

结果:

MannequinCharacter_Player是MannequinCharacter类的一个实例,MannequinCharacter类继承关系如下:

ALS Base Character => Character / ACharacter => Pawn / APawn => Actor / AActor => Object / UObject => UObjectBaseUtility => UObjectBase

值得注意的是除了主线继承以外,有些父类继承的接口:

ALS Base Character  => ALS Interface
APawn => INavAgentInterface

MannequinCharacter类几乎是一个空类,所以下文不再提及;Character及其以上的类为引擎内置类,不是本文的关注点。所以接下来重点分析ALS Base Character 类 和 ALS Interface 接口

1.2 class ALS Base Character

class ALS Base Character 主要实现了:

  1. 控制角色的rotation,见Manage Character Rotation(tick) 、 Interface Events
  2. 实现角色的多种运动方式的相互切换(ALS_MovementMode  ALS_Stance ALS_Gait), 速度的控制,见Do Every Frame(tick) 、 ALS Events、Default Character Events
  3. 角色的初始化逻辑,见Begin Play
  4. Player Input的处理,例如各种键盘、鼠标事件,见PlayerInputGraph
  5. 相机系统, 见Camara System
  6. 布娃娃系统, 见Ragdoll System
  7. 网络系统,服务端相关的逻辑, 见Networked Events

结合本文的主题,接下来之重点介绍前2项,3-7接跳过。

1.3 角色rotation的控制

函数SetCharacterRotation

控制角色的rotation的核心代码在函数SetCharacterRotation(TargetRotation, InterpRotation, InterpSpeed)

参数:TargetRotation rotation 目标旋转; InterpRotation bool 是否插值;InterpSpeed float 插值速度

SetCharacterRotation 最终会调用引擎的SetActorRotation(NewRotation)来实现旋转。

Jump状态、IsMoving状态,都是直接调用的SetCharacterRotation,不再赘述,下面介绍IsMoving为False的情况。

Not IsMoving时的角色转向(TurnInPlace)

基本原理:在播放TurnInPlace旋转动画的时候,根据动画设定的轨迹,每帧对角色增加一个旋转增量。

 TurnInPlace对角色执行旋转的代码在:Interface Events => AddCharacterRotation_BPI

可以看到,  AddCharacterRotation_BPI主要执行了函数AddCharacterRotation(rotation addAmount),addAmount是一个旋转的增量,是给当前角色rotation加上addAmount。

AddCharacterRotation_BPI是在播放TurnInPlace相关动画的时候,逐帧触发的:具体见以ALS_N_Turn_L为前缀的骨骼动画,里面有一个名为TurnInPlace_AnimNotityState的AnimNotityState,TurnInPlace_AnimNotityState中保存的有驱动Character的旋转轨迹。

具体播放动画的逻辑在:Mannequin_AnimBP蓝图

首先是用Montage对ALS_N_Turn_L为前缀的骨骼动画封装;然后在Mannequin_AnimBP蓝图中新建Montage变量(以N_Turn为前缀的变量),用以保存动画的索引。

在函数TurnInPlace(Delay) 和 TurnInPlace(Responsive)中,都会调用Montage变量进行动画的播放,Delay是通过鼠标左键转动镜头的时候用到,Responsive是通过鼠标右键转动镜头的时候用到;区别就是前者会加一个0.5秒左右的延迟;后者是实时响应旋转的。TurnInPlace函数决定了具体播放哪一个Montage变量,以及播放速率;大体逻辑为:旋转方向在60~130之间播放转90度的动作,130~180播放转全身的动作。

TurnInPlace的调用位置:Mannequin_AnimBP > 事件图表 > Do Every Frame > While Grounded > Turn In Place

1.4 角色速度的控制

由于走蹲切换,疾跑慢走的切换都是键盘事件触发的,这块逻辑从PlayerInputGraph里顺藤摸瓜即可,不再赘述,重点介绍加速机制,因为Neox的角色控制器默认是没有加速这个机制的。

Unreal引擎速度控制代码分析

Unreal角色控制器的代码在:CharacterMovementComponent.cpp

速度控制的逻辑主要在函数:

CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration)

这个函数的核心就是计算Velocity += Acceleration * DeltaTime,里面一堆if分支只是为了处理一些特殊情况。各个参数的含义:DeltaTime为帧时间,Friction是摩擦加速度,bFluid是否在流体中(游泳或者飞行会用到),BrakingDeceleration是刹车加速度。

TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)

这个函数是CharacterMovementComponent的每帧逻辑的入口,在这里我们可以看到Acceleration的计算方法:

Acceleration = ScaleInputAcceleration(ConstrainInputAcceleration(InputVector));

所以,最核心的加速度计算就是ScaleInputAcceleration:

FVector UCharacterMovementComponent::ScaleInputAcceleration(const FVector& InputAcceleration) const
{
	return GetMaxAcceleration() * InputAcceleration.GetClampedToMaxSize(1.0f);
}

GetMaxAcceleration获取的就是MaxAcceleration属性,是由脚本层设置的。

InputVector的设置方法最终也是脚本层调用函数:

  • Pawn.AddMovementInput函数
  • PawnMovementComponent.AddInputVector函数

蓝图层(脚本层)分析

根据引擎的分析结果,在脚本层搜索MaxAcceleration,AddMovementInput即可找到相关代码。

AddMovementInput本质上就是键盘或摇杆的方向输入,具体逻辑见:PlayerInputGraph => MovementInput => PlayerMovementInput => Normal Input

MaxAcceleration其实就是角色的最大加速度,脚本层主要有两块用到:

  1. Update ALS Character Movement Settings
  2. Do Every Frame => Do While Grounded => Custom Acceleration

第1个是在状态切换 或者 状态对应的速度发生改变的时候调用

第2个主要是在Standing状态下,且处于Running或Sprint状态下才会每帧执行;主要为了实现每帧根据玩家的旋转角来设置不同的加速度,旋转角度越大,加速度越小。Sprint和Running是共用一个基准加速度(Running Acceleration),然后乘上在CustomAcceleration函数里乘上不同的系数(MovementInput/VelocityDifference),MovementInput/VelocityDifference表示相对于上一帧的旋转角度,旋转角小于45度,则系数为1,加速度比较大;旋转角大于130度,则系数为0.2,加速度比较小。

3 关键动画分析

掌握了上文的unreal的使用技巧,读懂动画蓝图Mannequin_AnimBP的逻辑并不难。

本章还待完善,因为有需求单插进来了,所以先暂停,后续有时间再补充

3.1 Unreal的融合节点简介

https://www.cnblogs.com/xiaoyaoliu/articles/14501740.html

3.2 逐个动画简介

本节主要按照策划的要求,分析每个骨骼动画都用在了哪里。

站立姿势的Idle

ALS_N_Idle_Additive(呼吸动画,可以和正常走跑叠加),ALS_N_Idle_Pose(普通Idle)

ALS_N_Locomotion

走跑动画

ALS_N_Stop_LF 和 ALS_N_Stop_RF

高速状态下停下来的动作

ALS_LF_Pivot(极速转向的动作)

ALS_N_Lean_Grounded(走跑、蹲行状态下,角色前后左右的倾斜效果)

ALS_N_Idle_Additive_Pose(不倾)、ALS_N_Lean_F_Pose(前倾)、ALS_N_Lean_B_Pose(后倾)、ALS_N_Lean_L_Pose(左倾)、ALS_N_Lean_R_Pose(右倾)

ALS_N_Lean_InAir(下坠状态下,角色前后左右的倾斜效果)

ALS_N_InAir_Additive_Pose(不倾)、ALS_N_InAir_Lean_F_Pose(前倾)、ALS_N_InAir_Lean_B_Pose(后倾)、ALS_N_InAir_Lean_L_Pose(左倾)、ALS_N_InAir_Lean_R_Pose(右倾)

ALS_N_AO(各方向的look动画,用动画融合实现LookAt)

ALS_N_AO

  左转180度 左转90度 正前方 右转90度 右转190
向上看 ALS_N_AO_LU180 ALS_N_AO_LU90 ALS_N_AO_FU ALS_N_AO_RU90 ALS_N_AO_RU180
平视 ALS_N_AO_L180 ALS_N_AO_L90 ALS_N_AO_F ALS_N_AO_R90 ALS_N_AO_R180
向下看 ALS_N_AO_LD180 ALS_N_AO_LD90 ALS_N_AO_FD ALS_N_AO_RD90 ALS_N_AO_RD180

ALS_N_Turn(正常姿势,静止状态下,跟随镜头的转身动作)

所有ALS_N_Turn_为前缀的动作

跳跃相关动作

ALS_Flail ALS_N_Additive_LandCompression ALS_N_FallLoop ALS_N_Jump ALS_N_Land

Ragdoll状态下站起的动作

ALS_C_GetUpFromBack(躺着站起) ALS_C_GetUpFromFront(趴着站起) ALS_Curl ALS_Flail(jump fall也会用到)

下蹲相关动作

暂时不做下蹲,所以简单列举一下。

ALS_N_to_C_Idle(站立到蹲下) ALS_C_Idle_Additive(呼吸) ALS_C_Idle_Pose(普通idle),其他ALS_C_开头的动作。

ALS_LF_Locomotion ALS_LF_Stop(瞄准状态下的走跑冲动画)

ALS_N_to_LF_Idle(从idle到瞄准的过渡),所有ALS_LF_为前缀的动作。

我们暂时不需要瞄准,所以日后再研究。

未来的工作

这个样例也包含了脚步ik、ragdoll的相关逻辑,将来有时间也可以分析下,应该也有可以值得借鉴的东西。

 

posted on 2021-03-08 20:14  逍遥流  阅读(475)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3