Implemented Stop by foot planted and pivot feet curve or foot flags selection

This commit is contained in:
mrlee207 2025-05-14 12:38:48 +07:00 committed by LongLy
parent 501111ec24
commit 406b4e03ae
14 changed files with 198 additions and 130 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 51 KiB

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,6 @@
#include "AnimInstances/OLSBaseLinkedLayerAnimInstance.h"
#include "KismetAnimationLibrary.h"
#include "AnimInstances/OLSBaseLayerAnimInstance.h"
void UOLSBaseLinkedLayerAnimInstance::NativeInitializeAnimation()
@ -59,37 +58,27 @@ void UOLSBaseLinkedLayerAnimInstance::NativeThreadSafeUpdateSkeletonControlData(
{
OrientationWarpingAlpha = GetCurveValue(EnableOrientationWarpingName);
bIsLeftFootFarFromTarget = UKismetAnimationLibrary::K2_DistanceBetweenTwoSocketsAndMapRange(
GetOwningComponent(), IKFootLeft, RTS_World,
IKTargetFootLeft, RTS_World, false,
0.f, 0.f, 0.f, 0.f) > 8.0f;
bIsRightFootFarFromTarget = UKismetAnimationLibrary::K2_DistanceBetweenTwoSocketsAndMapRange(
GetOwningComponent(), IKFootRight, RTS_World,
IKTargetFootRight, RTS_World, false,
0.f, 0.f, 0.f, 0.f) > 8.0f;
// const float feetPositionValue = GetCurveValue(FeetPositionCurveName);
// bIsRightFootPlanted = feetPositionValue > 0.5f;
// bIsLeftFootPlanted = FMath::Abs(feetPositionValue) > 0.5f;
FeetPositionCurve = GetCurveValue(FeetPositionCurveName);
bIsRightFootPlanted = FeetPositionCurve > FootPlantedThreshold;
bIsLeftFootPlanted = FMath::Abs(FeetPositionCurve) > FootPlantedThreshold;
// If neither foot is planted, use the last valid foot
if (!bIsRightFootFarFromTarget && !bIsLeftFootFarFromTarget)
if (!bIsRightFootPlanted && !bIsLeftFootPlanted)
{
if (bWasRightFootPlantingChanged)
{
bIsRightFootFarFromTarget = true;
bIsRightFootPlanted = true;
}
else
{
bIsLeftFootFarFromTarget = true;
bIsLeftFootPlanted = true;
}
}
else
{
// Update the last valid foot
bWasRightFootPlantingChanged = bIsRightFootFarFromTarget;
bWasRightFootPlantingChanged = bIsRightFootPlanted;
bWasLeftFootPlantingChanged = bIsLeftFootPlanted;
}
}
@ -169,7 +158,7 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStartCycleAnimation(const
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.StartCycle.
GetMovementAnimationByAngle(
velocityDirection, angle, bIsRightFootFarFromTarget);
velocityDirection, angle, bIsRightFootPlanted);
}
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectCycleAnimation(const bool isCrouching,
@ -192,16 +181,21 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectPivotAnimation(const bool
const EOLSGait gait,
const EOLSCardinalDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const
const float angle,
float& outPivotTime) const
{
if (isAiming)
{
outPivotTime = 0.2f;
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.GetPivotFromHipDirection(hipDirection).
GetMovementAnimationByCardinalDirection(velocityDirection);
}
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Pivot.GetLeftOrRightByAngle(
angle, bIsLeftFootFarFromTarget, bIsRightFootFarFromTarget);
return (bUseFeetFlagsForPivot)
? GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Pivot.GetLeftOrRightAnim(
angle, bIsLeftFootPlanted, bIsRightFootPlanted, outPivotTime)
: GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Pivot.GetLeftOrRightAnim(
angle, FeetPositionCurve, outPivotTime);
}
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStopCycleAnimation(const bool isCrouching,
@ -217,7 +211,7 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStopCycleAnimation(const b
GetMovementAnimationByCardinalDirection(velocityDirection);
}
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.StopCycle.GetLeftOrRightAnim(bIsRightFootFarFromTarget);
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Stop.GetLeftOrRightStopAnim(FeetPositionCurve);
}
FVector2D UOLSBaseLinkedLayerAnimInstance::SelectPlayRateByLocomotionState(
@ -306,7 +300,7 @@ void UOLSBaseLinkedLayerAnimInstance::ProcessTurnInPlaceTransitionLogic(const fl
bool UOLSBaseLinkedLayerAnimInstance::ShouldSelectNewPivotAnimation(const float lastPivotTime) const
{
return ShouldLookingOrAimingDirectionSelectNewPivotAnimation(lastPivotTime);
return ShouldLookingOrAimingDirectionSelectNewPivotAnimation(lastPivotTime) || ShouldVelocityDirectionSelectNewPivotAnimation(lastPivotTime);
}
bool UOLSBaseLinkedLayerAnimInstance::ShouldLookingOrAimingDirectionSelectNewPivotAnimation(const float lastPivotTime) const
@ -314,6 +308,11 @@ bool UOLSBaseLinkedLayerAnimInstance::ShouldLookingOrAimingDirectionSelectNewPiv
return (bIsLookingOrAimingDirection && lastPivotTime > 0.0f);
}
bool UOLSBaseLinkedLayerAnimInstance::ShouldVelocityDirectionSelectNewPivotAnimation(const float lastPivotTime) const
{
return (bIsLookingOrAimingDirection && lastPivotTime > 0.0f && bWasRightFootPlantingChanged != bIsRightFootPlanted);
}
UOLSBaseLayerAnimInstance* UOLSBaseLinkedLayerAnimInstance::GetBaseMainAnimInstance() const
{
return BaseMainAnimInstance;

View File

@ -117,8 +117,19 @@ class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetMovementAn
return result;
}
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_Stop::GetLeftOrRightStopAnim(const float feetPosition) const
{
return (feetPosition > 0.f ? StopR : StopL);
}
void FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnimSet(float feetPosition,
FOLSMovementAnimSet_ForwardFacing_Pivot& outAnimSet) const
{
outAnimSet = (feetPosition > 0.f) ? Pivot_RightFoot : Pivot_LeftFoot;
}
void FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnimSet(const bool isLeftFootPlanted,
const bool isRightFootPlanted, FOLSMovementAnimSet_ForwardFacing_Pivot& outAnimSet) const
const bool isRightFootPlanted, FOLSMovementAnimSet_ForwardFacing_Pivot& outAnimSet) const
{
if (isLeftFootPlanted)
{
@ -130,18 +141,25 @@ void FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnimSet(const bool
}
}
UAnimSequence* FOLSMovementAnimSets_ForwardFacing_StopCycle::GetLeftOrRightAnim(const bool isRightFootPlanted) const
{
return (isRightFootPlanted ? StopCycle_RightFoot : StopCycle_LeftFoot);
}
class UAnimSequence* FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightByAngle(const float angle,
const bool isLeftFootPlanted,
const bool isRightFootPlanted) const
class UAnimSequence* FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnim(const float angle,
const bool isLeftFootPlanted, const bool isRightFootPlanted, float& outPivotTime) const
{
FOLSMovementAnimSet_ForwardFacing_Pivot animSet;
GetLeftOrRightAnimSet(isLeftFootPlanted, isRightFootPlanted, animSet);
outPivotTime = PivotTime;
return (angle > 0.f) ? animSet.Pivot180R : animSet.Pivot180L;
}
class UAnimSequence* FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnim(const float angle,
const float feetPosition, float& outPivotTime) const
{
FOLSMovementAnimSet_ForwardFacing_Pivot animSet;
GetLeftOrRightAnimSet(feetPosition, animSet);
outPivotTime = PivotTime;
return (angle > 0.f) ? animSet.Pivot180R : animSet.Pivot180L;
}

View File

@ -82,7 +82,8 @@ protected:
const EOLSGait gait,
const EOLSCardinalDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const;
const float angle,
float& outPivotTime) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors")
class UAnimSequence* SelectStopCycleAnimation(const bool isCrouching,
@ -120,6 +121,9 @@ protected:
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Pivot")
bool ShouldLookingOrAimingDirectionSelectNewPivotAnimation(const float lastPivotTime) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Pivot")
bool ShouldVelocityDirectionSelectNewPivotAnimation(const float lastPivotTime) const;
protected:
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe))
@ -199,16 +203,23 @@ protected:
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|OrientationWarping")
float OrientationWarpingAlpha = 0.f;
protected:
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|FeetPosition")
float FeetPositionCurve = 0.0f;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|FeetPosition")
uint8 bWasRightFootPlantingChanged : 1 = false;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|FeetPosition")
uint8 bIsRightFootFarFromTarget : 1 = true;
uint8 bWasLeftFootPlantingChanged : 1 = false;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|FeetPosition")
uint8 bIsLeftFootFarFromTarget : 1 = true;
uint8 bIsRightFootPlanted : 1 = true;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|SkeletonControl|FeetPosition")
uint8 bIsLeftFootPlanted : 1 = true;
protected:
@ -220,6 +231,9 @@ protected:
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|Pivots")
float TimeAtPivotStop = 0.f;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|Pivots")
float PivotTime = 0.f;
protected:
@ -264,19 +278,36 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition")
FName FeetPositionCurveName = NAME_None;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition")
FName IKFootRight = NAME_None;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition")
FName IKTargetFootRight = NAME_None;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition")
FName IKFootLeft = NAME_None;
/**
* Threshold value to determine if a foot is considered planted on the ground.
* Range: 0.0 to 1.0, where:
* - Values closer to 0 make foot planting detection more sensitive
* - Values closer to 1 require more definitive foot contact
* Default value of 0.4 provides a balanced detection for most animations
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition",
meta = (ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0"))
float FootPlantedThreshold = 0.4f;
/**
* Determines the method used for selecting pivot animations based on foot positioning.
*
* When true:
* - Uses explicit foot planting flags (isLeftFootPlanted, isRightFootPlanted)
* - More precise control over pivot selection
* - Better for complex animation transitions
*
* When false:
* - Uses simplified feet position value
* - Relies on animation curves for foot position
* - More suitable for basic movement patterns
*
* @note This affects how pivot animations are chosen in FOLSMovementAnimSets_ForwardFacing_Pivot
* @see FOLSMovementAnimSets_ForwardFacing_Pivot::GetLeftOrRightAnim
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|AnimSet|FeetPosition")
FName IKTargetFootLeft = NAME_None;
uint8 bUseFeetFlagsForPivot : 1 = true;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings|StrideWarping")
float StrideWarpingBlendInDurationScaled = .2f;

View File

@ -181,10 +181,29 @@ public:
};
USTRUCT(BlueprintType)
struct FOLSMovementAnimSet_ForwardFacing_Pivot
struct FOLSMovementAnimSet_ForwardFacing_Stop
{
GENERATED_BODY()
public:
class UAnimSequence* GetLeftOrRightStopAnim(const float feetPosition) const;
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Stop Anim Set")
TObjectPtr<class UAnimSequence> StopL = nullptr;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Stop Anim Set")
TObjectPtr<class UAnimSequence> StopR = nullptr;
};
USTRUCT(BlueprintType)
struct FOLSMovementAnimSet_ForwardFacing_Pivot
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Pivot Anim Set")
@ -202,14 +221,23 @@ struct FOLSMovementAnimSets_ForwardFacing_Pivot
protected:
void GetLeftOrRightAnimSet(const bool isLeftFootPlanted, const bool isRightFootPlanted,
void GetLeftOrRightAnimSet(const bool isLeftFootPlanted,
const bool isRightFootPlanted,
FOLSMovementAnimSet_ForwardFacing_Pivot& outAnimSet) const;
void GetLeftOrRightAnimSet(float feetPosition,
FOLSMovementAnimSet_ForwardFacing_Pivot& outAnimSet) const;
public:
class UAnimSequence* GetLeftOrRightByAngle(const float angle,
class UAnimSequence* GetLeftOrRightAnim(const float angle,
const bool isLeftFootPlanted,
const bool isRightFootPlanted) const;
const bool isRightFootPlanted,
float& outPivotTime) const;
class UAnimSequence* GetLeftOrRightAnim(const float angle,
const float feetPosition,
float& outPivotTime) const;
public:
@ -218,24 +246,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Pivot Anim Set")
FOLSMovementAnimSet_ForwardFacing_Pivot Pivot_RightFoot;
};
USTRUCT(BlueprintType)
struct FOLSMovementAnimSets_ForwardFacing_StopCycle
{
GENERATED_BODY()
public:
class UAnimSequence* GetLeftOrRightAnim(const bool isRightFootPlanted) const;
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Pivot Anim Set")
TObjectPtr<class UAnimSequence> StopCycle_LeftFoot;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement Pivot Anim Set")
TObjectPtr<class UAnimSequence> StopCycle_RightFoot;
float PivotTime = 0.0f;
};
USTRUCT(BlueprintType)
@ -257,15 +270,14 @@ public:
void GetPlayRateByLocomotionState(const EOLSLocomotionStatePlayRate& state, FVector2D& outPlayRate) const;
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Sets")
FVector2D PlayRate_Start = FVector2D::ZeroVector;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Sets")
FVector2D PlayRate_Pivot = FVector2D::ZeroVector;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Sets")
FVector2D PlayRate_Cycle = FVector2D::ZeroVector;
};
@ -286,7 +298,7 @@ public:
FOLSMovementAnimSets_ForwardFacing_Pivot Pivot;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
FOLSMovementAnimSets_ForwardFacing_StopCycle StopCycle;
FOLSMovementAnimSet_ForwardFacing_Stop Stop;
};
USTRUCT(BlueprintType)