一、控制角色旋转
- 摄像机旋转和角色旋转应该是两个独立的事件(比如游戏中拖动小眼睛那个操作)。因此,我们需要分离控制相机的鼠标控制旋转
ControlRotation
和角色旋转Pawn's Rotation
。 - 具体操作:在
Player
自身的Pawn
属性里取消勾选“使用控制器旋转Yaw”。并把弹簧臂中的“摄像机设置”的“使用Pawn控制旋转”开启。
一些思考:
- 取消勾选“使用控制器旋转Yaw”那么角色的 Yaw 旋转将不再由控制器直接控制。角色的旋转将会依赖于其他因素,比如角色的移动方向或是动画系统的设置。这会让角色不再跟随鼠标的移动进行旋转,但仍然可以使用键盘控制左右移动(注意:移动并不是旋转)
- 弹簧臂中的“使用Pawn控制旋转”如果开启这个选项,摄像机会跟随角色的旋转进行调整,从而保持一个固定的视角相对于角色。比如和平精英人物视角要跟随角色,但是向大世界俯瞰那种,就让角色自己动但相机一直一个方向
3. 还需要把Player
的“角色移动”中的“将旋转朝向运动”勾选,这样当我们在按A/D
左右移动时,角色会转向相应的方向,而不是斜着身子偏移(像那种2D接球游戏也许就不用开这个选项)
二、代码实现
以上是在蓝图中的设置,接下来是C++代码如何实现
- 要设置“旋转朝向移动”,首先要知道获取人物的“移动组件”,在头文件
"GameFramework/CharacterMovementComponent.h"
中
#include "GameFramework/CharacterMovementComponent.h"
// 关闭“使用控制器旋转Yaw”
bUseControllerRotationYaw = false;
// 开启“使用Pawn控制旋转”
SpringArmComp->bUsePawnControlRotation = true;
// 获取“角色移动”组件,然后开启“将旋转朝向运动”
GetCharacterMovement()->bOrientRotationToMovement = true;
- 此时运行关卡,按下左移不松手,就会发现角色一直在原地打转(相当于朝向左边的基础上的左边的左边的左边…)
- 但是我们需要的是:按下前进,角色转向相机方向,沿相机正前方向前;按下左键后,角色在原来初始朝向的基础上转向左方,然后再这个固定的方向上移动。也就是说在移动时需要一个表示空间方向的方向向量
vector
,且这个向量在按下键盘地时间段内是一个定值。
4.FRotator
结构体里有变量Yaw,Pitch,Roll
,并提供计算出朝向向量vector
的方法
前后移动的代码修改如下:
void ASurCharacter::MoveForward(float value)
{
FRotator ControlRot = GetControlRotation();
// 转向只关注水平Yaw方向,因此置0防止影响
ControlRot.Pitch = 0;
ControlRot.Roll = 0;
// 获取相机(鼠标控制器)的朝向,并朝这个方向移动
AddMovementInput(ControlRot.Vector(), value);
}
一些思考:
为什么使用控制器朝向而不获取角色朝向?
- 尽管摄像机会跟随角色的旋转,但控制器(尤其是用于处理玩家输入的控制器)的朝向不一定总是与角色的朝向完全一致。控制器的朝向通常基于玩家的输入,例如鼠标的移动方向。角色的朝向可能会受动画、移动状态等因素影响,不一定每时每刻都与控制器完全同步。
- 控制器的朝向通常直接反映玩家的输入方向,代表了玩家希望角色移动或视角转向的方向。在复杂的游戏逻辑中,角色的朝向可能受动画、物理效果等影响,而控制器的朝向直接反映玩家当前的输入意图。
- 左右移动只需要在相机朝向基础上向左或右旋转90°即可。
- 在UE中XYZ轴的正向分别对应前方、右方和上方,显示的箭头颜色分别为红色、绿色和蓝色(三基色的习惯顺序)
左右移动的代码修改如下:
void ASurCharacter::MoveRight(float value)
{
FRotator ControlRot = GetControlRotation();
ControlRot.Pitch = 0;
ControlRot.Roll = 0;
// 获取相机(鼠标控制器)的朝向,转向右侧,并朝这个方向移动;传入的Y表示右侧
FVector RightVector = FRotationMatrix(ControlRot).GetScaledAxis(EAxis::Y);
AddMovementInput(RightVector, value);
}
7.对FVector RightVector = FRotationMatrix(ControlRot).GetScaledAxis(EAxis::Y);
的进一步理解:
(1)控制器旋转(ControlRot):表示玩家的输入方向。(是提取了按下的旋转方向,而不是原来的)
(2)旋转矩阵(FRotationMatrix):将 ControlRot 转换为旋转矩阵,这个矩阵可以用来获取在当前旋转下的各种方向向量。
(3)提取 Y 轴向量(GetScaledAxis(EAxis::Y)):Y 轴向量表示相对于当前朝向的右方向。
拓展:
如果我按下右键,希望角色朝着右上45度方向移动的代码应该如何写?
- 代码解释:
(1)获取控制器的旋转:ControlRot 表示当前控制器的旋转(玩家输入的方向)。
(2)设置俯仰和滚动为零:确保只保留水平旋转(偏航)。
(3)创建旋转矩阵:通过 FRotationMatrix 将 ControlRot 转换为旋转矩阵。
(4)获取方向向量:从旋转矩阵中获取前向量(X轴向量)和右向量(Y轴向量)。
(5)计算45度旋转后的右向量:通过三角函数计算45度旋转后的右向量,使用 FMath::Cos 和 FMath::Sin 函数将前向量和右向量组合,得到旋转45度后的右向量。
(6)添加移动输入:使用 AddMovementInput 函数沿计算得到的旋转后方向移动。
void ASurCharacter::MoveRight45(float value)
{
// 获取控制器的旋转
FRotator ControlRot = GetControlRotation();
// 设置俯仰和滚动为零,只保留水平旋转(偏航)
ControlRot.Pitch = 0;
ControlRot.Roll = 0;
// 创建一个旋转矩阵
FRotationMatrix RotationMatrix(ControlRot);
// 从旋转矩阵中获取前向量
FVector ForwardVector = RotationMatrix.GetScaledAxis(EAxis::X);
// 从旋转矩阵中获取右向量
FVector RightVector = RotationMatrix.GetScaledAxis(EAxis::Y);
// 计算45度旋转后的右向量
FVector RotatedRightVector = FMath::Cos(FMath::DegreesToRadians(45.0f)) * RightVector +
FMath::Sin(FMath::DegreesToRadians(45.0f)) * ForwardVector;
// 添加移动输入
AddMovementInput(RotatedRightVector, value);
}