JustMakeGame 3. 数据驱动&曲线映射&基本数值

数据驱动

这一部分的含义是角色在不同的运动状态下,比如旋转模式不同(瞄准状态,正常状态),步态不同(走,跑,冲刺),姿态不同(蹲伏,站立)应该有不同运动属性设置。
这里的属性包括,速度(MaxWalkSpeed),加速度(MaxAcceleration),减速度(BrakingDecelerationWalking),摩檫力(BrakingFriction),摩檫力系数(BrakingFrictionFactor)

首先是一个数据结构的定义,配表用

USTRUCT(BlueprintType)
struct FCwlMovementSettings
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    float WalkSpeed = 0.0f;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    float RunSpeed = 0.0f;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    float SprintSpeed = 0.0f;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    UCurveVector* MovementCurve = nullptr;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    UCurveFloat* RotationRateCurve = nullptr;

    float GetSpeedForGait(const ECwlGait Gait) const
    {
        switch (Gait)
        {
        case ECwlGait::Running:
            return RunSpeed;
        case ECwlGait::Sprinting:
            return SprintSpeed;
        case ECwlGait::Walking:
            return WalkSpeed;
        default:
            return RunSpeed;
        }
    }
};

USTRUCT(BlueprintType)
struct FCwlMovementStanceSettings
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    FCwlMovementSettings Standing;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    FCwlMovementSettings Crouching;
};

USTRUCT(BlueprintType)
struct FCwlMovementStateSettings : public FTableRowBase
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    FCwlMovementStanceSettings VelocityDirection;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    FCwlMovementStanceSettings LookingDirection;

    UPROPERTY(EditAnywhere, Category = "Movement Settings")
    FCwlMovementStanceSettings Aiming;
};

根据 FCwlMovementStateSettings 创建DataTable 。然后对应的把ALSV4的datatable配置数值抄过来。

然后我们看这个表有三行,分别对应正常的运动,灵活的运动,缓慢的运动
每一项按三种旋转模式继续分。
又按照姿态的站立,蹲下又细分。
3 x 3 x 2
这么多状态每一个都有对应的配置,表示这个状态下走,跑,冲刺的速度应该是多少。

曲线映射

这里主要解释上一小节,配置中,MovementCurve曲线的作用
回到上一篇最后更新数值的地方。不同的步态(走,跑,冲刺)对应不同的速度,加速度数值。

void ACwlCharacter::UpdateDynamicMovementSettings(ECwlGait AllowedGait)
{
    const FCwlMovementSettings MovementSettings = GetTargetMovementSettings();
    switch (AllowedGait)
    {
    case ECwlGait::Walking:
        GetCharacterMovement()->MaxWalkSpeed = MovementSettings.WalkSpeed;
        break;
    case ECwlGait::Running:
        GetCharacterMovement()->MaxWalkSpeed = MovementSettings.RunSpeed;
        break;
    case ECwlGait::Sprinting:
        GetCharacterMovement()->MaxWalkSpeed = MovementSettings.SprintSpeed;
        break;
    default:
        break;
    }

    FVector MovementCurve = MovementSettings.MovementCurve->GetVectorValue(MyCharacterMovementComponent->GetMappingSpeed());
    GetCharacterMovement()->MaxAcceleration = MovementCurve.X;
    GetCharacterMovement()->BrakingDecelerationWalking = MovementCurve.Y;
    GetCharacterMovement()->BrakingFriction = MovementCurve.Z;
}

第一部分比较简单,根据走,跑,冲刺选择不同的速度。
第二部分我们先看 GetMappingSpeed()

float UCwlMovement::GetMappingSpeed() const
{
    const float Speed = Velocity.Size2D();
    const float LocalWalkSpeed = CurrentMovementSettings.WalkSpeed;
    const float LocalRunSpeed = CurrentMovementSettings.RunSpeed;
    const float LocalSprintSpeed = CurrentMovementSettings.SprintSpeed;

    float SpeedMappingWalk = FMath::GetMappedRangeValueClamped(FVector2D(0, LocalWalkSpeed), FVector2D(0, 1), Speed);
    float SpeedMappingRun = FMath::GetMappedRangeValueClamped(FVector2D(LocalWalkSpeed, LocalRunSpeed), FVector2D(1, 2), Speed);
    float SpeedMappingSprint = FMath::GetMappedRangeValueClamped(FVector2D(LocalRunSpeed, LocalSprintSpeed), FVector2D(2, 3), Speed);

    if (Speed > LocalRunSpeed)
    {
        return SpeedMappingSprint;
    }
    if (Speed > LocalWalkSpeed)
    {
        return SpeedMappingRun;
    }
    return SpeedMappingWalk;
}

目的是将角色速度映射到【0,3】的范围
角色当前有一个速度值,我们画个数轴

0______________A(175)_______________B(375)________________C(650)
0______________A'(1)________________B'(2)_________________C'(3)

A点是走的速度,B是跑的速度,C点是冲刺的速度,当前速度speed落在第一行的某个点,我们可以根据速度范围获得所在的区间。
代码的意思是,把A,B,C映射到0~3的值,然后在读取曲线,从中读取对于数值。
然后我们再看曲线


对于代码,在UpdateDynamicMovementSettings的最后面

    FVector MovementCurve = MovementSettings.MovementCurve->GetVectorValue(MyCharacterMovementComponent->GetMappingSpeed());
    GetCharacterMovement()->MaxAcceleration = MovementCurve.X;
    GetCharacterMovement()->BrakingDecelerationWalking = MovementCurve.Y;
    GetCharacterMovement()->BrakingFriction = MovementCurve.Z;

图中曲线横轴0~3,纵轴是数值。看代码X,Y,Z对应不同的加速度,减速度,摩檫力
对比一下



在正常状态,灵敏,迟钝的不同曲线中,加速度的数值就不一样,意味从静止到运动的过程时间不一样。

比如这里红色的线。2开始有一小段,然后马上下降,意味着在冲刺状态的第一段速度加速度是很大的,后面加速度恒定一个小一点的值,
那么具体表现在角色身上就是,我刚刚按了shift,突然冲了一下,然后变慢了一点点。

上一篇
下一篇