源碼摘自官網guide,加上部分自己的理解和注釋
接上篇博客 本文實現一個可用WASD控制滾動的球體
先創建一個可見的球體:
在CollidingPawn.cpp的構造函數ACollidingPawn::ACollidingPawn()中添加一個球體,一個網格組件(mesh),一個彈簧臂和相機,代碼如下:
//創建一個球體 USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent")); //設置為根組件 RootComponent = SphereComponent; //設置半徑 SphereComponent->InitSphereRadius(40.0f); SphereComponent->SetCollisionProfileName(TEXT("Pawn")); // 創建並放置網格物體組件,這樣我們能看到球體的位置 UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation")); //如果不把網格附加到SphereComponent 就看不到球體 SphereVisual->AttachTo(RootComponent); static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere")); if (SphereVisualAsset.Succeeded()){ SphereVisual->SetStaticMesh(SphereVisualAsset.Object); SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f)); SphereVisual->SetWorldScale3D(FVector(0.8f)); } // 使用彈簧臂來讓相機獲得一種平滑、自然的運動。 // 彈簧臂的目的是讓視角跟SphereComponent保持一定距離,如果不加,效果像fps游戲的第一視角一樣 USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm")); SpringArm->AttachTo(RootComponent); SpringArm->RelativeRotation = FRotator(-45.f, 0.f, 0.f); //45度角 SpringArm->TargetArmLength = 400.0f; //彈簧臂長度 SpringArm->bEnableCameraLag = true; SpringArm->CameraLagSpeed = 3.f; // 創建相機並附加到彈簧臂 // 如果沒有相機 什么都看不到 UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera")); Camera->AttachTo(SpringArm, USpringArmComponent::SocketName);
然后配置按鍵: 打開ue編輯器, 選擇編輯->項目設置-> 輸入, 然后在右邊的axis mappings加入如下設置:
MoveForWard,MoveRight,Turn,Turn_Y 可自定義,表示跟各個按鍵的綁定關系。
然后創建一個類CollidingPawnMovementComponent繼承自PawnMovementComponent(控制pawn移動的組件),我們可以把WASD綁定的行為綁定到這個component上,然后把該component綁定到我們剛才創建的球體上:
CollidingPawnMovementComponent.cpp
#include "Demo.h" #include "CollidingPawnMovementComponent.h" void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // Make sure that everything is still valid, and that we are allowed to move. if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime)) { return; } // Get (and then clear) the movement vector that we set in ACollidingPawn::Tick FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f; if (!DesiredMovementThisFrame.IsNearlyZero()) { FHitResult Hit; SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit); // If we bumped into something, try to slide along it if (Hit.IsValidBlockingHit()) { SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit); } } };
然后在CollidingPawn.h中加入如下代碼:
class UCollidingPawnMovementComponent* OurMovementComponent;
先將movementComponent綁定到剛才加的球體上,在CollidingPawn構造函數底部加入如下代碼:
// Create an instance of our movement component, and tell it to update the root. OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent")); OurMovementComponent->UpdatedComponent = RootComponent;
為了讓游戲中的其他類知道CollidingPawn目前正在使用CollidingPawnMovementComponent作為移動控制組件,需要在CollidingPawn.h中加入以下代碼:
virtual UPawnMovementComponent* GetMovementComponent() const override;
然后在CollidingPawn.cpp中加入:
UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const { return OurMovementComponent; }
剛才我們已經將新創建的移動控制組件綁定到了球體上,現在需要把WASD觸發的函數綁定到移動組件上,在CollidingPawn中實現往前移動,往左移動,轉動視角的三個方法:
// 往前(后)移動 void ACollidingPawn::MoveForward(float AxisValue) { if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent)) { OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue); } } // 往左(右)移動 void ACollidingPawn::MoveRight(float AxisValue) { if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent)) { OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue); } } // 左右轉動視角 void ACollidingPawn::Turn(float AxisValue) { FRotator NewRotation = GetActorRotation(); NewRotation.Yaw += AxisValue; SetActorRotation(NewRotation); }
然后將這三個方法在ACollidingPawn::SetupPlayerInputComponent中注冊:
void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent) { Super::SetupPlayerInputComponent(InputComponent); InputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward); InputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight); InputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn); }
以上就完成了一個可用WASD移動和鼠標控制左右視角的球體
如果上下移動視角,可仿照以上的ACollidingPawn::Turn方法,將NewRotation.Yaw += AxisValue; 改為NewRotation.Pitch += AxisValue;即可