简单的移动


  在本例中我们将进行简单的移动设置:

  我们首先先在项目设置中设置我们的输入移动轴的定义,如下图:


  然后我们需要创建一个Pawn类,命名为MyPawn,在MyPawn.h中,我们写入以下声明:


    public:
        // 虚拟根组件
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
            USceneComponent* OurVisibleComponent;
        // 静态模型组件
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
            UStaticMeshComponent* StaticMesh;
        // 摄像机手臂
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
            class USpringArmComponent* CameraBoom;
        // 摄像机组件
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
            class UCameraComponent* FollowCamera;

    private:
        // 当前的速度向量
        UPROPERTY(EditAnywhere)
            FVector CurrentVelocity;
        // 当前的速度值
        UPROPERTY(EditAnywhere)
            float MaxSpeed;

    private:
        // 前后移动的函数,由InputComponent绑定
        void MoveForward(float value);
        // 左右移动的函数,由InputComponent绑定
        void MoveRight(float value);
						

  在其MyPawn.cpp中,我们写入以下定义:


    // 构造函数
    AMyPawn::AMyPawn() {
        // 允许Tick函数运行
        PrimaryActorTick.bCanEverTick = true;
        // 实例化根组件并绑定
        OurVisibleComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
        RootComponent = OurVisibleComponent;
        // 实例化模型组件并绑定在根组件下
        StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StiticMesh"));
        StaticMesh->SetupAttachment(RootComponent);
	
        // 实例化摄像机手臂并绑定在根组件下
        CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
        CameraBoom->SetupAttachment(RootComponent);
        // 设置摄像机手臂的参数设置
        CameraBoom->TargetArmLength = 150.f;
        CameraBoom->TargetOffset = FVector(0.f, 0.f, 60.f);
        CameraBoom->SetRelativeLocation(FVector(0.f, 0.f, 90.f));

        // 实例化摄像机并绑定在摄像机手臂上
        FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
        FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
        // 摄像机的参数设置
        FollowCamera->AddLocalOffset(FVector(0.f, 0.f, 60.f));
        FollowCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
	    
        // 初始化速度向量和速度的值
        CurrentVelocity = FVector(0);
        MaxSpeed = 100.f;
        // 设置为Player0,即为当前玩家控制的物体
        AutoPossessPlayer = EAutoReceiveInput::Player0;
    }
	
    // 前后移动函数
    void AMyPawn::MoveForward(float value) {
        // 通过轴映射传入的值判断方向的前后,并设置当前状态下速度的向量
        CurrentVelocity.X = value * MaxSpeed;
    }
	
    // 左右移动的函数
    void AMyPawn::MoveRight(float value) {
        // 通过轴映射传入的值判断方向的左右,并设置当前状态下速度的向量
        CurrentVelocity.Y = value * MaxSpeed;
    }
	
    // 绑定输入函数
    void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
        Super::SetupPlayerInputComponent(PlayerInputComponent);
        // 绑定轴映射对应的函数
        PlayerInputComponent->BindAxis("MoveForward", this, &AMyPawn::MoveForward);
        PlayerInputComponent->BindAxis("MoveRight", this, &AMyPawn::MoveRight);
    }
	
    // 每帧运行的函数Tick,DeltaTime为时间
    void AMyPawn::Tick(float DeltaTime) {
        Super::Tick(DeltaTime);
        // 定义新的位置坐标,速度乘以时间即为位移,用当位置加上位移量,即为移动后的位置
        FVector NewLocation = GetActorLocation() + CurrentVelocity * DeltaTime;
        // 设置新的位置
        SetActorLocation(NewLocation);
    }
						

  编译后,我们继承于我们的MyPawn新建一个蓝图类,命名为BP_Pawn,打开并指定我们BP_Pawn蓝图,选中StaticMesh组件,并绑定StiticMesh组件的模型,如下图:


  然后我们编译保存,运行,我们按下W,S,A,D,就会发现我们的Pawn进行了最简单的移动。但是我们发现,我们拖入物体的时候如果对物体进行了旋转,那么物体的移动将会发生错乱。


  因为这种移动方式是以世界坐标为基准,当物体进行转向之后,物体自身的X轴于世界坐标的X轴不对应,换句话说,指向的方向不一样,而我们上述的移动以世界坐标为基准,那么这种移动方式将会出错,若需要使用物体自身坐标为基准进行移动,那么我们需要做以下修改:


    在MyPawm.h中:
    public:
        // 箭头组件
        UPROPERTY(EditAnywhere)
            class UArrowComponent* ArrowComponent;
        /*
            这个组件特别重要,如果不声明不定义,我们的Pawn将无法知道
            GetActorForwardVector这个向量的方向,从而无法知道正方向,
            这个组件的作用就是定义这个物体的正方向
        */
						
    在MyPawm.cpp中:
    构造函数加入ArrowComponent组件的实例化
    ArrowComponent->CreateDefaultSubobject<UArrowComponent>(TEXT("ArrowComponent"));
    ArrowComponent->SetupAttachment(RootComponent);

    // 前后移动函数
    void AMyPawn::MoveForward(float value) {
        // 获取物体自身的向前方向的向量,乘于是否反向和速度,即可获得向前后移动的方向
        CurrentVelocity = GetActorForwardVector() * value * MaxSpeed;
    }
	
    // 左右移动的函数
    void AMyPawn::MoveRight(float value) {
        // 获取物体自身的向右方向的向量,乘于是否反向和速度,即可获得向左右移动的方向
        CurrentVelocity = GetActorRightVector() * value * MaxSpeed;
    }
						

  通过以上的方式,我们就完成了简单的移动,并且物体无论如何转向,移动的方向都不会出错。