斯坦福UE4 + C++课学习记录 4:控制旋转

一、控制角色旋转

  1. 摄像机旋转角色旋转应该是两个独立的事件(比如游戏中拖动小眼睛那个操作)。因此,我们需要分离控制相机的鼠标控制旋转ControlRotation和角色旋转Pawn's Rotation
  2. 具体操作:在Player自身的Pawn属性里取消勾选“使用控制器旋转Yaw”。并把弹簧臂中的“摄像机设置”的“使用Pawn控制旋转”开启。

一些思考:

  • 取消勾选“使用控制器旋转Yaw”那么角色的 Yaw 旋转将不再由控制器直接控制。角色的旋转将会依赖于其他因素,比如角色的移动方向或是动画系统的设置。这会让角色不再跟随鼠标的移动进行旋转,但仍然可以使用键盘控制左右移动(注意:移动并不是旋转)
  • 弹簧臂中的“使用Pawn控制旋转”如果开启这个选项,摄像机会跟随角色的旋转进行调整,从而保持一个固定的视角相对于角色。比如和平精英人物视角要跟随角色,但是向大世界俯瞰那种,就让角色自己动但相机一直一个方向

在这里插入图片描述
3. 还需要把Player的“角色移动”中的“将旋转朝向运动”勾选,这样当我们在按A/D左右移动时,角色会转向相应的方向,而不是斜着身子偏移(像那种2D接球游戏也许就不用开这个选项)

二、代码实现

以上是在蓝图中的设置,接下来是C++代码如何实现

  1. 要设置“旋转朝向移动”,首先要知道获取人物的“移动组件”,在头文件"GameFramework/CharacterMovementComponent.h"
#include "GameFramework/CharacterMovementComponent.h"

// 关闭“使用控制器旋转Yaw”
bUseControllerRotationYaw = false;
// 开启“使用Pawn控制旋转”
SpringArmComp->bUsePawnControlRotation = true;
// 获取“角色移动”组件,然后开启“将旋转朝向运动”
GetCharacterMovement()->bOrientRotationToMovement = true; 
  1. 此时运行关卡,按下左移不松手,就会发现角色一直在原地打转(相当于朝向左边的基础上的左边的左边的左边…)
  2. 但是我们需要的是:按下前进,角色转向相机方向,沿相机正前方向前;按下左键后,角色在原来初始朝向的基础上转向左方,然后再这个固定的方向上移动。也就是说在移动时需要一个表示空间方向的方向向量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);
} 

一些思考:
为什么使用控制器朝向而不获取角色朝向?

  • 尽管摄像机会跟随角色的旋转,但控制器(尤其是用于处理玩家输入的控制器)的朝向不一定总是与角色的朝向完全一致。控制器的朝向通常基于玩家的输入,例如鼠标的移动方向。角色的朝向可能会受动画、移动状态等因素影响,不一定每时每刻都与控制器完全同步。
  • 控制器的朝向通常直接反映玩家的输入方向,代表了玩家希望角色移动或视角转向的方向。在复杂的游戏逻辑中,角色的朝向可能受动画、物理效果等影响,而控制器的朝向直接反映玩家当前的输入意图。
  1. 左右移动只需要在相机朝向基础上向左或右旋转90°即可。
  2. 在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);
}

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值