移动介绍


  我们的第三人称模板的移动功能的思路与我们的简单移动中的思路又稍微有些不一样,他是直接调用了一些Characetr中内置好的移动函数来直接实现,首先,我们依旧要设置好项目的轴输入。


  然后在ThirdProjectCharacter.h中声明我们的两个移动函数


    protected:
        // 前后移动函数
        void MoveForward(float Value);
        // 左右移动函数
        void MoveRight(float Value);
						

  然后在ThirdProjectCharacter.cpp的SetupPlayerInputComponent中进行绑定


    PlayerInputComponent->BindAxis("MoveForward", this, &AThirdProjectCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &AThirdProjectCharacter::MoveRight);
						

  接下来,重头戏,我们写入那两个函数的定义


    // 前后移动函数
    void AThirdProjectCharacter::MoveForward(float Value) {
        // 控制器是否存在并且值不为0
        if ((Controller != NULL) && (Value != 0.0f)) {
            // 获取Controller的旋转值
            const FRotator Rotation = Controller->GetControlRotation();
            // 获取我们双脚的那个平面的旋转值,也就是Yaw轴,即Y轴旋转值
            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // 通过这个旋转值向量的旋转矩阵,获得他X轴的方向,即前后方向(这里的方向是相对于模型自身的)
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
            // 使用一个AddMovementInput函数,传入我们的方向,和我们的传入的值
            AddMovementInput(Direction, Value);
        }
    }
    // 左右移动函数同理
    void AThirdProjectCharacter::MoveRight(float Value) {
        // 控制器是否存在并且值不为0
        if ((Controller != NULL) && (Value != 0.0f)) {
            // 获取Controller的旋转值
            const FRotator Rotation = Controller->GetControlRotation();
            // 获取我们双脚的那个平面的旋转值,也就是Yaw轴,即Y轴旋转值
            const FRotator YawRotation(0, Rotation.Yaw, 0);

            // 通过这个旋转值向量的旋转矩阵,获得他Y轴的方向,即左右方向(这里的方向是相对于模型自身的)
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
            // 使用一个AddMovementInput函数,传入我们的方向,和我们的传入的值
            AddMovementInput(Direction, Value);
        }
    }
						

  这里的重点是AddMovementInput函数,我们可以通过Visual Studio来查看这个函数的源码,我们发现,这个函数是定义在Pawn类下的,并且定义如下:


    void APawn::AddMovementInput(FVector WorldDirection, float ScaleValue, bool bForce /*=false*/){
        // Pawn的移动控制组件
        UPawnMovementComponent* MovementComponent = GetMovementComponent();
        if (MovementComponent){
            // 传入方向乘于轴值,获取前后方向
            MovementComponent->AddInputVector(WorldDirection * ScaleValue, bForce);
        }
        else{
            Internal_AddMovementInput(WorldDirection * ScaleValue, bForce);
        }
    }    
						

  我们发现,他的原理就是通过传入一个方向向量,用这个方向向量来乘于一个轴的值,例如W为1,S为-1,那么通过这个简单的运算,我们就获取了移动的方向,我们通过AddInputVector这个函数,将这个方向传入我们的移动控制组件,并将角色进行移动,如果移动组件不存在,我们会直接调用Internal_AddMovementInput函数来移动,其传入参数一致,而我们的AddInputVector函数底层也是调用的Internal_AddMovementInput函数,其代码如下:


    void UPawnMovementComponent::AddInputVector(FVector WorldAccel, bool bForce /*=false*/){
        if (PawnOwner){
            // 调用这个Pawn的Internal_AddMovementInput函数
            PawnOwner->Internal_AddMovementInput(WorldAccel, bForce);
        }
    } 
						

  也就代表着实际控制我们角色移动的是Internal_AddMovementInput函数,而再往底层就涉及到引擎本身Pawn的底层代码了,过于深入本人也看不懂,从字面上而言,Internal_AddMovementInput函数就是用于控制我们的移动的,传入的参数就是我们要移动的方向的方向向量。我们的Character就是通过这个方式来控制我们的移动的。