Section 8: Advanced Movement - Lecture 124

Crouching Turn Animations
This commit is contained in:
charnet3d 2023-04-22 08:26:18 +00:00
parent 56fad37200
commit 82692124a4
29 changed files with 208 additions and 36 deletions

View File

@ -88,6 +88,8 @@ DoubleClickTime=0.200000
+ActionMappings=(ActionName="Select",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Right) +ActionMappings=(ActionName="Select",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Right)
+ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R) +ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R)
+ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Left) +ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Left)
+ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C)
+ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_RightThumbstick)
+AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W)
+AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) +AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S)
+AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Gamepad_LeftY) +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Gamepad_LeftY)

BIN
Content/_Game/Character/Animations/AimingAimOffset.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/_Game/Character/Animations/HipAimOffset.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/_Game/Maps/DefaultMap.umap (Stored with Git LFS)

Binary file not shown.

View File

@ -14,9 +14,15 @@ UShooterAnimInstance::UShooterAnimInstance() :
MovementOffsetYaw(0.f), MovementOffsetYaw(0.f),
LastMovementOffsetYaw(0.f), LastMovementOffsetYaw(0.f),
bAiming(false), bAiming(false),
CharacterYaw(0.f), TIPCharacterYaw(0.f),
CharacterYawLastFrame(0.f), TIPCharacterYawLastFrame(0.f),
RootYawOffset(0.f) RootYawOffset(0.f),
Pitch(0.f),
bReloading(false),
OffsetState(EOffsetState::EOS_Hip),
CharacterRotation(FRotator(0)),
CharacterRotationLastFrame(FRotator(0)),
YawDelta(0.f)
{ {
} }
@ -26,8 +32,9 @@ void UShooterAnimInstance::UpdateAnimationProperties(float DeltaTime)
ShooterCharacter = Cast<AShooterCharacter>(TryGetPawnOwner()); ShooterCharacter = Cast<AShooterCharacter>(TryGetPawnOwner());
if (!ShooterCharacter) return; if (!ShooterCharacter) return;
// Get the speed of the character from velocity // Get the lateral speed of the character from velocity
FVector Velocity{ ShooterCharacter->GetVelocity() }; FVector Velocity{ ShooterCharacter->GetVelocity() };
Velocity.Z = 0; Velocity.Z = 0;
Speed = Velocity.Size(); Speed = Velocity.Size();
@ -49,8 +56,28 @@ void UShooterAnimInstance::UpdateAnimationProperties(float DeltaTime)
} }
bAiming = ShooterCharacter->GetAiming(); bAiming = ShooterCharacter->GetAiming();
bReloading = ShooterCharacter->GetCombatState() == ECombatState::ECS_Reloading;
bCrouching = ShooterCharacter->IsCrouching();
if (bReloading)
{
OffsetState = EOffsetState::EOS_Reloading;
}
else if (bIsInAir)
{
OffsetState = EOffsetState::EOS_InAir;
}
else if (bAiming)
{
OffsetState = EOffsetState::EOS_Aiming;
}
else
{
OffsetState = EOffsetState::EOS_Hip;
}
TurnInPlace(); TurnInPlace();
Lean(DeltaTime);
} }
void UShooterAnimInstance::NativeInitializeAnimation() void UShooterAnimInstance::NativeInitializeAnimation()
@ -63,23 +90,26 @@ void UShooterAnimInstance::NativeInitializeAnimation()
void UShooterAnimInstance::TurnInPlace() void UShooterAnimInstance::TurnInPlace()
{ {
if (!ShooterCharacter) return; if (!ShooterCharacter) return;
if (Speed > 0)
Pitch = ShooterCharacter->GetBaseAimRotation().Pitch;
if (Speed > 0 || bIsInAir)
{ {
// Don't want to turn in place; Character is moving // Don't want to turn in place; Character is moving
RootYawOffset = 0.f; RootYawOffset = 0.f;
CharacterYaw = ShooterCharacter->GetActorRotation().Yaw; TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw;
CharacterYawLastFrame = CharacterYaw; TIPCharacterYawLastFrame = TIPCharacterYaw;
RotationCurve = 0.f; RotationCurve = 0.f;
RotationCurveLastFrame = 0.f; RotationCurveLastFrame = 0.f;
} }
else else
{ {
CharacterYawLastFrame = CharacterYaw; TIPCharacterYawLastFrame = TIPCharacterYaw;
CharacterYaw = ShooterCharacter->GetActorRotation().Yaw; TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw;
const float YawDelta { CharacterYaw - CharacterYawLastFrame }; const float TIPYawDelta { TIPCharacterYaw - TIPCharacterYawLastFrame };
// Root Yaw Offset, updated and clamped to [-180, 180] // Root Yaw Offset, updated and clamped to [-180, 180]
RootYawOffset = UKismetMathLibrary::NormalizeAxis(RootYawOffset - YawDelta); RootYawOffset = UKismetMathLibrary::NormalizeAxis(RootYawOffset - TIPYawDelta);
// 1.0 if turning, 0.0 if not // 1.0 if turning, 0.0 if not
const float Turning { GetCurveValue(TEXT("Turning")) }; const float Turning { GetCurveValue(TEXT("Turning")) };
@ -99,14 +129,28 @@ void UShooterAnimInstance::TurnInPlace()
RootYawOffset > 0 ? RootYawOffset -= YawExcess : RootYawOffset += YawExcess; RootYawOffset > 0 ? RootYawOffset -= YawExcess : RootYawOffset += YawExcess;
} }
} }
/*if (GEngine)
{
GEngine->AddOnScreenDebugMessage(1, -1, FColor::Blue,
FString::Printf(TEXT("CharacterYaw: %f"), CharacterYaw));
GEngine->AddOnScreenDebugMessage(2, -1, FColor::Red,
FString::Printf(TEXT("RootYawOffset: %f"), RootYawOffset));
}*/
} }
} }
void UShooterAnimInstance::Lean(float DeltaTime)
{
if (!ShooterCharacter) return;
CharacterRotationLastFrame = CharacterRotation;
CharacterRotation = ShooterCharacter->GetActorRotation();
const FRotator Delta { UKismetMathLibrary::NormalizedDeltaRotator(CharacterRotation, CharacterRotationLastFrame) };
const double Target { Delta.Yaw / DeltaTime };
const double Interp { FMath::FInterpTo(YawDelta, Target, DeltaTime, 6.f) };
YawDelta = FMath::Clamp(Interp, -90.f, 90.f);
// if (GEngine)
// {
// GEngine->AddOnScreenDebugMessage(
// 3,
// -1,
// FColor::Cyan,
// FString::Printf(TEXT("YawDelta: %f"), YawDelta)
// );
// }
}

View File

@ -7,6 +7,19 @@
#include "ShooterAnimInstance.generated.h" #include "ShooterAnimInstance.generated.h"
class AShooterCharacter; class AShooterCharacter;
UENUM(BlueprintType)
enum class EOffsetState : uint8
{
EOS_Aiming UMETA(DisplayName = "Aiming"),
EOS_Hip UMETA(DisplayName = "Hip"),
EOS_Reloading UMETA(DisplayName = "Reloading"),
EOS_InAir UMETA(DisplayName = "InAir"),
EOS_MAX UMETA(DisplayName = "DefaultMax")
};
/** /**
* *
*/ */
@ -27,6 +40,9 @@ public:
protected: protected:
/** Handle turning in place variables */ /** Handle turning in place variables */
void TurnInPlace(); void TurnInPlace();
/** Handle calculations for leaning while running */
void Lean(float DeltaTime);
private: private:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = true)) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = true))
@ -55,11 +71,11 @@ private:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = true)) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = true))
bool bAiming; bool bAiming;
/** Yaw of the character this frame */ /** Turn In Place: Yaw of the character this frame; Only updated when standing still and not in the air */
float CharacterYaw; float TIPCharacterYaw;
/** Yaw of the character the previous frame */ /** Turn In Place: Yaw of the character the previous frame; Only updated when standing still and not in the air */
float CharacterYawLastFrame; float TIPCharacterYawLastFrame;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turn In Place", meta = (AllowPrivateAccess = true)) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turn In Place", meta = (AllowPrivateAccess = true))
float RootYawOffset; float RootYawOffset;
@ -69,4 +85,30 @@ private:
/** Rotation curve value last frame */ /** Rotation curve value last frame */
float RotationCurveLastFrame; float RotationCurveLastFrame;
/** The pitch of the aim rotation used for aim offset */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turn In Place", meta = (AllowPrivateAccess = true))
float Pitch;
/** True when reloading, used to prevent aim offset when reloading */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turn In Place", meta = (AllowPrivateAccess = true))
bool bReloading;
/** Offset state; used to determine which Aim Offset to use */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Turn In Place", meta = (AllowPrivateAccess = true))
EOffsetState OffsetState;
/** Yaw of the character this frame */
FRotator CharacterRotation;
/** Yaw of the character the previous frame */
FRotator CharacterRotationLastFrame;
/** Yaw delta used for leaning while running in the blendspace */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Lean", meta = (AllowPrivateAccess = true))
double YawDelta;
/** True when crouching */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Crouching", meta = (AllowPrivateAccess = true))
bool bCrouching;
}; };

View File

@ -60,7 +60,8 @@ AShooterCharacter::AShooterCharacter() :
Starting9mmAmmo(85), Starting9mmAmmo(85),
StartingARAmmo(120), StartingARAmmo(120),
// Combat variables // Combat variables
CombatState(ECombatState::ECS_Unoccupied) CombatState(ECombatState::ECS_Unoccupied),
bCrouching(false)
{ {
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.bCanEverTick = true;
@ -149,6 +150,9 @@ void AShooterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCo
PlayerInputComponent->BindAction("Reload", IE_Pressed, this, PlayerInputComponent->BindAction("Reload", IE_Pressed, this,
&AShooterCharacter::ReloadButtonPressed); &AShooterCharacter::ReloadButtonPressed);
PlayerInputComponent->BindAction("Crouch", IE_Pressed, this,
&AShooterCharacter::CrouchButtonPressed);
} }
// Called every frame // Called every frame
@ -686,7 +690,7 @@ void AShooterCharacter::ReloadWeapon()
if (!EquippedWeapon) return; if (!EquippedWeapon) return;
// Do we have ammo for the correct type // Do we have ammo for the correct type
if (CarryingAmmo() && EquippedWeapon->GetAmmo() < EquippedWeapon->GetMagazineCapacity()) if (CarryingAmmo() && !EquippedWeapon->ClipIsFull())
{ {
CombatState = ECombatState::ECS_Reloading; CombatState = ECombatState::ECS_Reloading;
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
@ -759,3 +763,11 @@ void AShooterCharacter::ReleaseClip()
{ {
EquippedWeapon->SetMovingClip(false); EquippedWeapon->SetMovingClip(false);
} }
void AShooterCharacter::CrouchButtonPressed()
{
if (!GetCharacterMovement()->IsFalling())
{
bCrouching = !bCrouching;
}
}

View File

@ -161,6 +161,9 @@ protected:
/** Called from Animation Blueprint with ReleaseClip notify */ /** Called from Animation Blueprint with ReleaseClip notify */
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void ReleaseClip(); void ReleaseClip();
void CrouchButtonPressed();
private: private:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = true)) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = true))
USpringArmComponent* CameraBoom; USpringArmComponent* CameraBoom;
@ -337,7 +340,11 @@ private:
/* Scene component to attach to the Character's hand when reloading */ /* Scene component to attach to the Character's hand when reloading */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = true)) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = true))
USceneComponent* HandSceneComponent; USceneComponent* HandSceneComponent;
/** True when crouching */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = true))
bool bCrouching;
public: public:
/* Returns CameraBoom SubObject */ /* Returns CameraBoom SubObject */
FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; } FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
@ -358,4 +365,8 @@ public:
FVector GetCameraInterpLocation(); FVector GetCameraInterpLocation();
void GetPickupItem(AItem* Item); void GetPickupItem(AItem* Item);
FORCEINLINE ECombatState GetCombatState() const { return CombatState; }
FORCEINLINE bool IsCrouching() const { return bCrouching; }
}; };

View File

@ -65,6 +65,11 @@ void AWeapon::ReloadAmmo(int32 Amount)
Ammo += Amount; Ammo += Amount;
} }
bool AWeapon::ClipIsFull()
{
return Ammo >= MagazineCapacity;
}
void AWeapon::StopFalling() void AWeapon::StopFalling()
{ {
bFalling = false; bFalling = false;

View File

@ -86,4 +86,6 @@ public:
void ReloadAmmo(int32 Amount); void ReloadAmmo(int32 Amount);
FORCEINLINE void SetMovingClip(bool Move) { bMovingClip = Move; }; FORCEINLINE void SetMovingClip(bool Move) { bMovingClip = Move; };
bool ClipIsFull();
}; };