Published on

创建一个角色

Authors
  • avatar
    Name
    Ushen
    Twitter

在工程新建一个C++类,选择character,命名为MyCharacter会生成两个文件,分别是AMyCharacter.h和AMyCharacter.cpp。

继承的是Acharacter类。

初始有四个函数,分别是

  • Tick(): 每帧都会调用的函数。

  • SetUpPlayerInputComponent(): 绑定玩家输入的一个函数,参数是UInputComponent。

  • BeginPlaye(): 游戏开始调用的函数。

  • AMyCharacter(): 构造函数。

骨骼与摄像机

首先一个人物需要一个骨骼,还需要一个摄像机跟随移动。 在.h文件定义

//骨骼体定义
 UPROPERTY(VisibleAnywhere, Category = "Base")
  USkeletalMesh *SkeletalMesh;

  //弹簧臂定义
 UPROPERTY(VisibleAnywhere, Category = "Base")
  USpringArmComponent *SpringArmComp;

  //摄像机定义
 UPROPERTY(VisibleAnywhere, Category = "Base")
  UCameraComponent *CameraComp;

虚幻中的属性要用UPROPERTY修饰,其中参数有

VisibleAnywhere,在蓝图和编译器中可见,但是只读,read-only

EditAnywhere,是可编辑

BluprientReadOnly,蓝图只读,

等等。

Category是属性在面板中的显示类型。

在构造方法AMyCharacter中引用骨骼和创建摄像机。

默认的构造方法有一行

// 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;

当这个属性为true时,会每帧调用Tick()方法,不需要时可以关闭.

SkeletalMesh = LoadObject<USkeletalMesh>(NULL, TEXT("SkeletalMesh'/Game/UndeadPack/Lich/Mesh/SK_Lich.SK_Lich'"));
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));

在我们已经有资产的情况下,在编辑器右键资产,可以复制引用,使用LoadObject加载这个资产。

这里加载了骨骼体,和创建了一个摄像机组件,和弹簧臂组件。

然后就是角色跟组件的绑定与设置;

//位置 x,y,z
 GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
  //旋转 y,z,x
 GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
  //胶囊体半高,半径
 GetCapsuleComponent()->InitCapsuleSize(34, 88);
GetMesh()->SetSkeletalMesh(SkeletalMesh);
//弹簧跟随Character
 SpringArmComp->SetupAttachment(RootComponent);
 SpringArmComp->SetRelativeLocation(FVector(0, 0, 100));
 SpringArmComp->SetRelativeRotation(FRotator(-15, 0, 0));
 SpringArmComp->bUsePawnControlRotation = true;

  //设置摄像机父类是弹簧
 CameraComp->SetupAttachment(SpringArmComp);
 CameraComp->SetRelativeLocation(FVector::ZeroVector);
 CameraComp->bUsePawnControlRotation = false;

GetMesh()获取当前网格,

location和rotation是位置和旋转,

FVector和Frotator是位置和旋转的向量

代表的三维的位置的xyz和旋转的yzx

这里讲一下pitch,roll和yaw,

  • pitch就是y轴
  • roll就是z轴
  • yaw就是x轴

设置位置与旋转,胶囊体大小

这里的参数放在蓝图中编辑会比较方便,也能快速看到调整参数后的变化。

然后就是弹簧,弹簧的父类就是根组件RootComponent,跟随着当前角色

摄像机的父类是弹簧组件,跟随着弹簧移动。

在蓝图中调整好弹簧和摄像机的位置,就是玩家视角看到的角色。

这里是第三人称的摄像机位置,在角色的后上方。

bUsePawnControlRotation,是否跟着控制器旋转而旋转,

这里摄像机是false,弹簧臂是true

控制器旋转时,弹簧臂会跟着旋转,因为摄像机的会随着弹簧臂移动,所以在旋转时,玩家视角会围绕着RootComponent旋转,就是角色

  //不随着镜头转动而转动
  bUseControllerRotationPitch = false;
  bUseControllerRotationRoll = false;
  //随着镜头转动视角
  bUseControllerRotationYaw = true;

前面讲到bUseControllerRotation是是否跟着控制器旋转。

这里的pitch,roll,yaw也是前面的概念。

这里的设置表示,角色会随着控制器的x轴旋转而旋转。

也就是角色始终会朝向镜头前方,玩家只能看到角色的背面

如果bUseControllerRotationYaw=false;控制器旋转到角色前方,玩家就能看到角色正面。

角色移动

PlayerInputComponent->BindAxis("lookRight", this, &AMyCharacter::AddControllerYawInput);
 PlayerInputComponent->BindAxis("lookForward", this, &AMyCharacter::AddControllerPitchInput);
 PlayerInputComponent->BindAxis("moveRight", this, &AMyCharacter::MoveRight);
 PlayerInputComponent->BindAxis("moveForward", this, &AMyCharacter::MoveForward);

需要在编译器绑定按键,设置轴映射,

这里的BindAxis第一个参数就是添加的轴映射的名称。

void AMyCharacter::MoveForward(float Value)
{
  FRotator ControlRot = GetControlRotation();
  FRotator YawRotation(0, ControlRot.Yaw, 0);
  FVector Driection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

 AddMovementInput(Driection, Value);
}


void AMyCharacter::MoveRight(float Value)
{
  FRotator ControlRot = GetControlRotation();
  FRotator YawRotation(0, ControlRot.Yaw, 0);
  FVector Driection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

 AddMovementInput(Driection, Value);
}

GetControlRotation,获取当前控制的人物的旋转,也就是朝向。

这里的移动是前后左右,就是yaw,要把pitch和roll的值设置为0,面的干扰,

FrotationMatrix,朝向,X就是前后,Y就是左右,

然后AddMovementInput,往这个朝向移动value值。

这里移动不会改变角色朝向,角色始终面对前方。

如果需要角色朝着移动方向旋转,

需要修改玩家移动设置。

GetCharacterMovement() 角色移动

GetCharacterMovement()->bOrientRotationToMovement = true;

设置朝向随着移动方向

设置这个之后要把bUseControllerRotationYaw设为false,让玩家不随着镜头转动。

这个时候,角色会向前后左右方向旋转,但是当玩家按W前进时,会自动转向镜头方向。不会向角色本来朝向的前方走。


至此,一个能到处观看,能移动的角色就有了