Pitch 复制与轴压缩在 Unreal Engine 中

发布: (2026年3月7日 GMT+8 15:25)
6 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的正文内容(除代码块和 URL 之外的文字),我将把它翻译成简体中文并保持原有的 Markdown 格式。

Pawn 类

函数 GetBaseAimRotation()(在 APawn 类中可用)返回复制的俯仰角,可在 Blueprint 和 C++ 中使用。

Blueprint 步骤

  1. 调用 Get Base Aim Rotation 并获取其前向向量。
  2. 将该方向从世界空间逆变换到 Pawn 的局部空间(使用 Pawn 的世界变换)。
  3. 拆分得到的向量并读取 Pitch(俯仰)分量。

Aim offset diagram

C++ 实现

您可以使用 Kismet 数学库或原生的向量/旋转器函数——两种方法得到的结果相同。
如果使用 Kismet 库,请记得包含相应的头文件(#include "Kismet/KismetMathLibrary.h")。

头文件

// MyCharacter.h
class AMyCharacter : public ACharacter
{
    // ...

    /** Returns the replicated pitch value. */
    float GetReplicatedPitch() const;
};

使用 Kismet 数学库

// MyCharacter.cpp
float AMyCharacter::GetReplicatedPitch() const
{
    // World‑space aim direction from the replicated rotation
    const FVector AimDirectionWorld = UKismetMathLibrary::GetForwardVector(GetBaseAimRotation());

    // Convert to pawn‑local space
    const FVector AimDirectionLocal = UKismetMathLibrary::InverseTransformDirection(
        GetActorTransform(),
        AimDirectionWorld
    );

    // Build a rotator from the local X axis and read Pitch
    const FRotator AimRotationLocal = UKismetMathLibrary::MakeRotFromX(AimDirectionLocal);

    return AimRotationLocal.Pitch;
}

使用原生函数

float AMyCharacter::GetReplicatedPitch() const
{
    // World‑space aim direction from the replicated rotation
    const FVector AimDirectionWorld = GetBaseAimRotation().Vector();

    // Convert to pawn‑local space (no scaling)
    const FVector AimDirectionLocal = ActorToWorld().InverseTransformVectorNoScale(AimDirectionWorld);

    // Build a rotator from the local vector and read Pitch
    const FRotator AimRotationLocal = AimDirectionLocal.Rotation();

    return AimRotationLocal.Pitch;
}

两种实现都会返回从拥有客户端复制过来的相同 Pitch 值。

内部工作原理

GetBaseAimRotation() 的行为会根据 pawn 是否拥有有效的控制器(即本地受控)或没有(即模拟代理)而不同。

当存在控制器时

FVector POVLoc;
FRotator POVRot;

if (Controller != nullptr && !InFreeCam())
{
    Controller->GetPlayerViewPoint(POVLoc, POVRot);
    return POVRot;          // 使用玩家实际的视角旋转
}

该函数直接返回控制器当前的视角旋转。

当不存在控制器(模拟代理)时

// 使用 pawn 自身的旋转作为回退
POVRot = GetActorRotation();

// 如果俯仰角为零,则回退到复制的 RemoteViewPitch
if (FMath::IsNearlyZero(POVRot.Pitch))
{
    const UWorld* World = GetWorld();
    const UDemoNetDriver* DemoNetDriver = World ? World->GetDemoNetDriver() : nullptr;

    // 回放/录制路径 – 正常游戏中忽略
    if (DemoNetDriver && DemoNetDriver->IsPlaying() &&
        DemoNetDriver->GetPlaybackEngineNetworkProtocolVersion() GetControlRotation().Pitch);
    }
}
  • SetRemoteViewPitch 使用 FRotator::CompressAxisToByte 将浮点数俯仰角压缩为一个字节 (uint8)。
  • 在客户端,GetBaseAimRotation() 使用 FRotator::DecompressAxisFromByte 将该字节解压回完整的 float 俯仰角。

摘要

  • 使用 GetBaseAimRotation() 获取已复制的视角旋转。
  • 将前向向量转换到局部空间并提取俯仰角(可通过 Kismet Math Library 或原生函数实现)。
  • 在底层,Unreal 会在服务器上将俯仰角压缩为单字节(RemoteViewPitch),并在远程客户端解压,从而实现低成本、高效的复制。

你可以通过添加自定义的已复制、压缩变量并在 PreReplication 中处理它们,将相同的模式应用于复制其他轴或自定义数值。

在 UE4 中复制 Pawn 的俯仰角

下面是处理 pawn 类内部俯仰角复制的相关代码。

1. 获取远程视图俯仰角

void APawn::GetRemoteViewPitch()
{
    // Example of retrieving the remote view pitch
    float Pitch = RemoteViewPitch;               // RemoteViewPitch is a byte
    float DecompressedPitch = FRotator::DecompressAxisFromByte(Pitch);
    // Use DecompressedPitch as needed…
}

2. 设置远程视图俯仰角

void APawn::SetRemoteViewPitch(float NewRemoteViewPitch)
{
    // Compress pitch to 1 byte
    RemoteViewPitch = FRotator::CompressAxisToByte(NewRemoteViewPitch);
}

Note: SetRemoteViewPitchfloat 轴值压缩为单个字节,以便在网络上传输。


使用方法

  1. 检查 pawn 类 – 打开 pawn 的源文件,定位上述两个函数。
  2. 理解流程
    • SetRemoteViewPitch 在服务器(或拥有客户端)上调用,以在复制前压缩俯仰角。
    • GetRemoteViewPitch(或你实现的相应 getter)在远程机器上将字节解压回可用的 float
  3. 利用内置复制 – 在大多数情况下,你可以依赖 UE4 对 pawn 的默认俯仰角复制。
  4. 自定义轴压缩 – 如果需要压缩其他轴,遵循相同的模式:在 复制前 的函数中压缩,在读取复制值时解压。

最后思考

即使一开始细节看起来有些繁琐,重新审视 pawn 类中的这些函数也能帮助你巩固理解。大多数情况下,引擎自带的俯仰角复制已经足够,但了解如何手动压缩轴可以为自定义网络需求提供灵活性。

祝你好运!

0 浏览
Back to Blog

相关文章

阅读更多 »

可视化组件

可视化组件 可视化组件是仅在编辑器中使用的组件,负责在屏幕或 HUD 上绘制非渲染的调试信息。它们轻量级,……

Unreal Engine 3D 流体转 Flipbook

我一直想使用 alembic 创建血液特效,但这些模拟可能会变得非常庞大,对许多游戏来说不切实际。Unreal Engine 包含一个 bui...