Lyra学习007:Lyra角色移动机制解析

详细解析如何在LyraStarterGame项目中创建一个完整的GameFeature插件,包括角色移动的实现机制。

一、创建GameFeature插件基础结构

1. 创建GameFeature插件模板

# 在引擎或项目中使用插件模板
# 或手动创建以下结构:
YourPlugin/
├── Source/
│   ├── YourPlugin/
│   │   ├── YourPlugin.Build.cs
│   │   ├── YourPlugin.h
│   │   └── YourPlugin.cpp
│   └── YourPluginEditor/
├── Config/
├── Content/
└── YourPlugin.uplugin

2. GameFeatureData配置

// Config/GameFeatureData.json
{
    "GameFeatureName": "YourFeature",
    "GameFeatureActions": [
        {
            "ActionType": "WorldAction",
            "WorldData": {
                "MapsToLoad": [],
                "GameModes": [],
                "Experiences": []
            }
        }
    ]
}

二、创建角色和Experience定义

1. 创建自定义Experience

// YourExperience.h
UCLASS()
class UYourGameExperience : public ULyraExperienceDefinition
{
    GENERATED_BODY()
    
public:
    UYourGameExperience(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
    
protected:
    virtual void OnExperienceLoaded(const ULyraExperienceDefinition* Experience) override;
    
    // 添加你的角色pawn类
    UPROPERTY(EditDefaultsOnly, Category = "Gameplay")
    TSoftClassPtr<APawn> DefaultPawnClass;
    
    // 添加输入配置
    UPROPERTY(EditDefaultsOnly, Category = "Input")
    TObjectPtr<ULyraInputConfig> InputConfig;
};

2. 配置PawnData

// 在Content中创建Blueprints/Pawns/BP_YourCharacter
// 继承自ALyraCharacter

// 创建PawnData资产:
// 1. 右键创建 -> Lyra -> Pawn Data
// 2. 配置:
//    - Input Config: 你的输入配置
//    - Ability Sets: 能力集
//    - Camera Mode: LyraCameraMode
//    - Character Class: BP_YourCharacter

三、Lyra角色移动实现机制

1. 移动组件架构

Lyra使用分层移动组件:

// 核心移动组件:ULyraCharacterMovementComponent
UCLASS()
class ULyraCharacterMovementComponent : public UCharacterMovementComponent
{
    GENERATED_BODY()
    
    // 基础移动实现
    virtual void UpdateBasedMovement(float DeltaSeconds) override;
    virtual void PhysWalking(float deltaTime, int32 Iterations) override;
    
    // Lyra特定功能
    void HandleMoverGroundMovement();
    void ApplyAccumulatedForces();
    
    // 网络同步
    virtual void PerformMovement(float DeltaTime) override;
};

2. 输入处理流程

// 1. 输入绑定(LyraInputComponent)
ULyraInputComponent::BindNativeActions(
    const ULyraInputConfig* InputConfig,
    const ULyraInputConfig::FInputActionCallback& PressedFunc,
    const ULyraInputConfig::FInputActionCallback& ReleasedFunc);

// 2. 输入转换为移动(LyraHeroComponent)
void ULyraHeroComponent::Input_Move(const FInputActionValue& InputActionValue)
{
    APawn* Pawn = GetPawn<APawn>();
    if (Pawn)
    {
        const FVector2D Value = InputActionValue.Get<FVector2D>();
        const FRotator MovementRotation(0.0f, Pawn->GetControlRotation().Yaw, 0.0f);
        
        if (Value.X != 0.0f)
        {
            const FVector MovementDirection = MovementRotation.RotateVector(FVector::RightVector);
            Pawn->AddMovementInput(MovementDirection, Value.X);
        }
        
        if (Value.Y != 0.0f)
        {
            const FVector MovementDirection = MovementRotation.RotateVector(FVector::ForwardVector);
            Pawn->AddMovementInput(MovementDirection, Value.Y);
        }
    }
}

3. Gameplay Ability System集成

// 移动能力(LyraGameplayAbility_Jump)
ULYRA_API ULyraGameplayAbility_Jump : public ULyraGameplayAbility
{
    void ActivateAbility(
        const FGameplayAbilitySpecHandle Handle,
        const FGameplayAbilityActorInfo* ActorInfo,
        const FGameplayAbilityActivationInfo ActivationInfo,
        const FGameplayEventData* TriggerEventData) override
    {
        // 触发跳跃
        ACharacter* Character = CastChecked<ACharacter>(ActorInfo->AvatarActor.Get());
        Character->Jump();
    }
};

4. 网络复制和预测

// LyraCharacterMovementComponent网络同步
void ULyraCharacterMovementComponent::ServerMove_Implementation(
    float TimeStamp,
    FVector_NetQuantize10 InAccel,
    FVector_NetQuantize100 ClientLoc,
    uint8 CompressedMoveFlags,
    uint8 ClientRoll,
    uint32 View,
    UPrimitiveComponent* ClientMovementBase,
    FName ClientBaseBoneName,
    uint8 ClientMovementMode)
{
    // 服务器端移动处理
    // ...
}

四、完整GameFeature配置示例

1. GameFeature Action配置

// 自定义GameFeatureAction
UCLASS()
class UYourGameFeatureAction_AddInputConfig : public UGameFeatureAction
{
    GENERATED_BODY()
    
public:
    UPROPERTY(EditAnywhere, Category="Input")
    TSoftObjectPtr<ULyraInputConfig> InputConfig;
    
    virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context) override;
    virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) override;
};

2. 在Experience中引用

// YourExperience.cpp
void UYourGameExperience::OnExperienceLoaded(const ULyraExperienceDefinition* Experience)
{
    Super::OnExperienceLoaded(Experience);
    
    // 加载Pawn数据
    if (DefaultPawnClass.IsValid())
    {
        APawn* DefaultPawn = DefaultPawnClass->GetDefaultObject<APawn>();
        // 配置pawn组件
    }
    
    // 应用输入配置
    if (InputConfig)
    {
        ULyraInputComponent* InputComponent = FindInputComponent();
        if (InputComponent)
        {
            InputComponent->BindAbilityActions(
                InputConfig,
                this,
                &ThisClass::Input_AbilityInputTagPressed,
                &ThisClass::Input_AbilityInputTagReleased);
        }
    }
}

五、部署和使用

1. 打包GameFeature

# GameFeatures/YourFeature/Config/GameFeature.ini
[/Script/GameFeatures.GameFeaturePluginProtocol_InstallBundle]
+InstallBundles=MyFeatureContent

[/Script/GameFeatures.GameFeatureData]
+Actions=/Game/YourFeature/Actions/GFAction_YourAction.GFAction_YourAction

2. 运行时激活

// 在GameMode或Experience中激活
UGameFeaturesSubsystem& Subsystem = UGameFeaturesSubsystem::Get();
Subsystem.LoadAndActivateGameFeaturePlugin("YourFeature", FGameFeaturePluginLoadComplete());

六、关键实现要点

  1. 移动预测:Lyra使用CharacterMovementComponent的预测机制
  2. 输入处理:通过LyraInputComponent和InputConfig绑定
  3. 能力系统:移动与Gameplay Ability System深度集成
  4. 网络同步:使用UE5的移动组件网络复制
  5. 模块化设计:通过GameFeature实现功能模块化

这个架构允许你创建完全自定义的角色移动系统,同时保持与Lyra框架的兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值