|
发表于 2023-3-11 16:36:10
|
显示全部楼层
【UE5】【3C】ALSv4重构分析(二) : Locomotion导读 - 知乎 (zhihu.com)
Sixze/ALS-Refactored: Completely reworked and improved version of the Community Version of Advanced Locomotion System V4. (github.com)
我几个月前也尝试阅读alsv4,不过很快就放弃了。因为那个实在是太难阅读了。主要是设计完全耦合在了一起。als-refactor无疑是一个很好的版本,它有模块设计(有点像java里的maven,前端里的webpack)。至少让我知道从何读起。很好笑的事,我在读alsv4初始版本的时候,是从摄像机那里读起的,这无疑是南辕北辙。重构后的alsv4,应该是从als这个模块读起,让我们开始吧。
搭建基本框架
新建一个插件

rider新建plugin
把github项目里配置文件里的内容给复制过来,替换掉rider生成的默认内容。比如下面那个改成PreDefault。AlSCanmera等内容现在不用。其实如果你懂配置文件的话,可以直接按需复制粘贴。这个配置文件也不难,基本一看就懂。

ALS.uplugin

ALS.Build.cs
project_name_api
在新版的alsv4中,采用了模块化设计。所以你就会在很多类中看到类似project_name_api的宏来声明类。这种声明可以使得外面的模块也可以用到这个类。
What does the macro ProjectName_API do? - Programming & Scripting / C++ - Epic Developer Community Forums (unrealengine.com)
Hey where does ENGINE_API defined? - Development / Programming & Scripting - Epic Developer Community Forums (unrealengine.com)

AlsAnimationInstance.h
GameTag
我们这里就把几个tag文件复制过来,然后再看一看源码。
WTF Is? Gameplay Tags in Unreal Engine 4 ( UE4 ) - YouTube
Gameplay标签 | 虚幻引擎文档 (unrealengine.com)
看过官方文档,我们知道GameTag可以直接在project setting里直接设定。但是在alsv4中,GameTag是写在cpp文件中,声明在AlsGameplayTags.h里。从虚幻的源码可以看出,声明和定义tag用得是不同的类。
此时我们编译一下就会发现,gametags就出现在了project setting里的gametag里。

project setting里的gametags

AlsGameplayTags.h

NativeGameplayTags.h

AlsGameplayTags.cpp
无脑复制state和settings下的类
state其实这里应该是状态机里的状态。

AlsFeetState.h
比如在这个脚步状态中,有ikAmount,lockAmount,像是调整脚ik的一些数值。如何使用还要看后面。

AlsRollingSettings.h
这个setting记录一些设置,比如旋转插入属性,是否在地上滚动等。
大致看一下AlsCharacter
UCLASS(AutoExpandCategories = ("Settings|Als Character", "Settings|Als Character|Desired State", "State|Als Character"))
这个感觉没啥用,应该能去掉。应该就是自动打开目录,因为这个搜索也挺方便的。坐等打脸。
<hr/> UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = &#34;Als Character&#34;)
TObjectPtr<UAlsCharacterMovementComponent> AlsCharacterMovement;

AlsCharacterMovemet
<hr/> UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character&#34;)
TObjectPtr<UAlsCharacterSettings> Settings;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character&#34;)
TObjectPtr<UAlsMovementSettings> MovementSettings;

AlsCharacter Settings
<hr/> UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character|Desired State&#34;)
bool bDesiredAiming;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character|Desired State&#34;)
FGameplayTag DesiredRotationMode{AlsRotationModeTags::LookingDirection};
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character|Desired State&#34;)
FGameplayTag DesiredStance{AlsStanceTags::Standing};
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = &#34;Settings|Als Character|Desired State&#34;)
FGameplayTag DesiredGait{AlsGaitTags::Running};

desired something
<hr/> UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
bool bSimulatedProxyTeleported;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient, Meta = (ShowInnerProperties))
TWeakObjectPtr<UAlsAnimationInstance> AnimationInstance;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FGameplayTag LocomotionMode{AlsLocomotionModeTags::Grounded};
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FGameplayTag RotationMode{AlsRotationModeTags::LookingDirection};
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FGameplayTag Stance{AlsStanceTags::Standing};
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FGameplayTag Gait{AlsGaitTags::Walking};
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FGameplayTag LocomotionAction;
// Raw replicated view rotation. For smooth rotation use FAlsViewState::Rotation.
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FRotator RawViewRotation;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FAlsViewState ViewState;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FVector_NetQuantizeNormal InputDirection;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FAlsLocomotionState LocomotionState;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
int32 MantlingRootMotionSourceId;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FVector_NetQuantize100 RagdollTargetLocation;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FAlsRagdollingState RagdollingState;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = &#34;State|Als Character&#34;, Transient)
FAlsRollingState RollingState;

locomotion等一些东西
<hr/> explicit AAlsCharacter(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

AlsCharacter的初始化函数
Why &#34;#if WITH_EDITOR&#34; in some souce code? - Development / Platform & Builds - Epic Developer Community Forums (unrealengine.com)
with_editor会调用editor的api,但是在打包游戏时,这个就会被忽略。

B_ALS_Character的设置 |
|