打折的时候买了这个资产,纯蓝图项目,里面的飞行动画不错。逻辑也可以做一定的参考,直接接入进来。
初步实现
我希望在空中按shift进入飞行状态。
void ACwlBasePlayer::InputBeginSprint(const FInputActionValue& InputValue)
{
if (GetMovementState() == ECwlMovementState::InAir)
{
FlyComponent->Server_StartFly();
FlyComponent->StartFly();
return ;
}
DesiredGait = ECwlGait::Sprinting;
Server_SetDesiredGait(DesiredGait);
}
飞行状态按空格跳一下退出飞行状态。
void ACwlBasePlayer::InputBeginJump(const FInputActionValue& InputValue)
{
// ...
if (GetMovementState() == ECwlMovementState::Fly)
{
FlyComponent->Server_StopFly();
FlyComponent->StopFly();
return;
}
// ...
进入退出飞行状态。核心是设置移动组件状态 OwnerCharacter->GetMyMovementComponent()->SetMovementMode(MOVE_Flying);
void UCwlFlyComponent::StartFly()
{
if (!IsComponentReady())
{
UE_LOG(LogTemp, Error, TEXT("UCwlFlyComponent::StartFly Component Init Fail"));
return ;
}
OwnerCharacter->SetMovementState(ECwlMovementState::Fly);
OwnerCharacter->GetMyMovementComponent()->SetMovementMode(MOVE_Flying);
}
void UCwlFlyComponent::StopFly()
{
if (!IsComponentReady())
{
UE_LOG(LogTemp, Error, TEXT("UCwlFlyComponent::StopFly Component Init Fail"));
return ;
}
OwnerCharacter->SetMovementState(ECwlMovementState::InAir);
OwnerCharacter->GetMyMovementComponent()->SetMovementMode(MOVE_Falling);
}
如果是飞行状态输入直接接到飞行组件里面处理。
FlyComponent->Move(OutForwardAxis, OutRightAxis);
这里直接按摄像机的前,右方向加就好了。
void UCwlFlyComponent::Move(float ForwardAxis, float RightAxis)
{
if (!IsComponentReady())
{
UE_LOG(LogTemp, Error, TEXT("UCwlFlyComponent::StopFly Component Init Fail"));
return ;
}
APlayerController* PlayerController = Cast<APlayerController>(OwnerCharacter->GetController());
if (PlayerController == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("UCwlFlyComponent::Move PlayerController is nullptr"));
return ;
}
APlayerCameraManager* PlayerCameraManager = PlayerController->PlayerCameraManager;
if (PlayerCameraManager == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("UCwlFlyComponent::Move PlayerCameraManager is nullptr"));
return ;
}
OwnerCharacter->AddMovementInput(PlayerCameraManager->GetActorForwardVector(), ForwardAxis);
OwnerCharacter->AddMovementInput(PlayerCameraManager->GetActorRightVector(), RightAxis);
}
在tick中把角色的Rotation往摄像机的Rotation插值。
FRotator CameraRotator = PlayerCameraManager->GetCameraRotation();
CameraRotator.Pitch = 0.f;
FRotator NewRot = FMath::RInterpTo(OwnerCharacter->GetActorRotation(), CameraRotator, DeltaTime, 8.f);
OwnerCharacter->SetActorRotation(NewRot);
然后在动画蓝图里面计算一下各个方向的速度。
void UFlyAnimIns::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
if (ACwlCharacter* InCharacterBase = Cast<ACwlCharacter>(TryGetPawnOwner()))
{
FVector SpeedVector = InCharacterBase->GetVelocity();
FRotator CharacterRot = InCharacterBase->GetActorRotation();
SpeedVector = CharacterRot.UnrotateVector(SpeedVector);
if (UCharacterMovementComponent* InCharacterMovementComponent = Cast<UCharacterMovementComponent>(InCharacterBase->GetMovementComponent()))
{
float MaxFlySpeed = InCharacterMovementComponent->MaxFlySpeed;
FlySpeed.X = FMath::GetMappedRangeValueClamped(FVector2D(-MaxFlySpeed, MaxFlySpeed), FVector2D(-1.f, 1.f), SpeedVector.X);
FlySpeed.Y = FMath::GetMappedRangeValueClamped(FVector2D(-MaxFlySpeed, MaxFlySpeed), FVector2D(-1.f, 1.f), SpeedVector.Y);
FlySpeed.Z = FMath::GetMappedRangeValueClamped(FVector2D(-MaxFlySpeed, MaxFlySpeed), FVector2D(-1.f, 1.f), SpeedVector.Z);
}
}
}
然后准备一个根据速度方向倾斜的混合空间。
把飞行状态丢到这里
然后收工