2017年11月21日

幕后故事:在VR模式下的双脚移动

作者 Matthieu Vivant

3dRudder是用双脚控制的VR运动控制器,在VR模式下,坐着就可以用双脚操控场景,解放双手去选择、自定义或移动物体。当我们在各种VR项目中测试UE4插件,包括在VR和非VR游戏中3dRudder支持的三种移动类型(走/跑;盘旋;飞行)时,我们开始使用的是虚幻引擎的VR模式。于是我们立即想到,可以把这个插件集成到编辑器中,提供一种创新的场景操控方式,让这个已经很出色的工具进一步提升价值。770_3DRudder_Pic1.jpg目前,VR模式下在场景中四处移动的方法是用手推或拉环境,那为什么不使用一种让用户更自然地移动的方法呢?我们将3dRudder集成到VR模式中的目的是让开发者:

 

  • 在场景中直观地移动和盘旋,轻松地使用任何观察角度
  • 能够持续在桌前工作,不必去特定的VR设备点,轻松切换编辑器和VR模式
  • 不受房间大小限制
  • 只需要手动控制器来选择、自定义和移动物体

 

集成了VR模式后,开发者不但可以使用键盘/鼠标或游戏杆(XInput),还可以使用双脚在标准UE4编辑器中移动。
3dRudder与VR模式的集成

为了将3dRudder与VR模式集成,我们需要在现有的UE4插件中添加特定的代码,用于处理VR模式。 
770_3DRudder_Pic2.jpg
我们根据创建编辑器模块Wiki,为编辑器创建插件。

第一步是创建3dRudder编辑器模块:

1. 在3dRudder.uplugin中添加编辑器模块:
 
{
 "Name": "_3DRudderEditor",
 "Type": "Editor",
 "LoadingPhase": "PostEngineInit",
 "WhitelistPlatforms": [ "Win64", "Win32" ]
}

2. 将虚幻编辑器(UnrealEd)作为依赖关系添加到_3dRudderEditor.build.cs
 
PublicDependencyModuleNames.AddRange( new string[] {
    "Core", 
    "CoreUObject",      // Provides Actors and Structs
    "UnrealEd",
});


3. 创建继承以下类的F3DRudderEditorModule类:

a. IModuleInterface,让我们能够注册、启动和停止模块。
b. FTickableEditorObject,允许对每一帧做标记,并获得3dRudder的输入轴值,更新视口摄像机。
 
void F3DRudderEditorModule::Tick(float DeltaTime)
{
    //UE_LOG(_3DRudderEditor, Warning, TEXT("tick %f"), DeltaTime);
    // 3dRudder SDK
    ns3dRudder::CSdk* pSdk = ns3dRudder::GetSDK();
    // Mode : curve
    ns3dRudder::ModeAxis mode = ns3dRudder::ValueWithCurveNonSymmetricalPitch;
    // Curves for each axis (Pitch, Roll, Yaw, UpDown)
    ns3dRudder::CurveArray *curves = new ns3dRudder::CurveArray;
    // Only one device (0)
    uint32 i = 0;
    if (pSdk->IsDeviceConnected(i))
    {
        // Axis : X, Y, Z, rZ
        ns3dRudder::Axis axis;
        // Status of 3dRudder
        ns3dRudder::Status status;
        if (pSdk->GetAxis(i, mode, &axis, curves) == ns3dRudder::Success)
        {
            status = pSdk->GetStatus(i);            
            if ((status == ns3dRudder::InUse || status == ns3dRudder::ExtendedMode) && GetDefault()->bActive)
                UpdateViewportCamera(FVector(axis.m_aY, axis.m_aX, axis.m_aZ), axis.m_rZ);
        }
    }
}

UpdateViewportCamera中,我们让FEditorViewportClient对象调用MoveViewport函数。我们在用于游戏手柄/操控杆的UE4源代码中发现了这个函数,其作用是在编辑器中移动摄像机。
 
void F3DRudderEditorModule::UpdateViewportCamera(const FVector& translation, float yaw)
{
    //UE_LOG(_3DRudderEditor, Warning, TEXT("tick %f"), yaw);
    if (translation.IsZero() && yaw == 0)
        return;
    if (GEditor != nullptr && GEditor->GetActiveViewport() != nullptr && GEditor->GetActiveViewport()->GetClient() != nullptr)
    {
        FEditorViewportClient* client = StaticCast(GEditor->GetActiveViewport()->GetClient());      
        if (client != nullptr && !client->Viewport->IsPlayInEditorViewport())
        {           
            const FVector speed = GetDefault()->Translation;
            const float speedRotation = GetDefault()->RotationYaw;
            // X Y local
            FVector local(translation.X * speed.X, translation.Y * speed.Y, 0);
            FVector world = client->GetViewRotation().RotateVector(local);
            // Z world
            world += FVector(0.0f, 0.0f, translation.Z * speed.Z);
            // Pitch Yaw Roll
            FRotator rotation(0, yaw * speedRotation, 0);
            // Move Camera of Viewport with 3dRudder
            client->MoveViewportCamera(world, rotation);
        }
    }
}


4. 我们还创建了一个U3DRudderSettings类,用于在编辑器首选项中显示和保存一些特定参数:

a. 用于激活/停用摄像机运动的布尔值
b. 用于更改X、Y、Z轴上的运动速度/速率的三维向量
c. 用于更改Z轴(绕Y轴的旋转)上的旋转速度/速率的浮点数
 
UCLASS(config = Editor, defaultconfig)
class U3DRudderSettings : public UObject
{
    GENERATED_BODY()
public:
    U3DRudderSettings(const FObjectInitializer& ObjectInitializer);
    /** Enable/Disable */
    UPROPERTY(EditAnywhere, config, Category = Move)
        bool bActive;
    /** Speed Translation */
    UPROPERTY(EditAnywhere, config, Category = Speed)
        FVector Translation;
    /** Speed Rotation (Yaw) */
    UPROPERTY(EditAnywhere, config, Category = Speed, meta = (DisplayName = "Rotation (Yaw)" ))
        float RotationYaw;
};

要访问这些设置,需要点击编辑(Edit)->编辑器首选项(Editor Preferences)->3dRudder->视口(Viewport)
770_3DRudder_Pic3.jpg
在更新这些值时,它们会保存到Config/DefaultEditor.ini中。这样每个项目都可以有不同的运动速度。
 
[/Script/_3DRudderEditor.3DRudderSettings]
Translation=(X=1.000000,Y=2.000000,Z=3.000000)
RotationYaw=5.000000
bActive=True

我们在一个空白的C++项目内部用Visual Studio 2015构建了这个插件。
770_3DRudder_Pic4.jpg
完整的代码可以在GitHub上找到,地址如下:
https://github.com/3DRudder/3DRudderSDK_Unreal_Engine

最后一步就是将插件包提交给虚幻市场团队,确保它能在最新版本的虚幻引擎(4.15、4.16、4.17和即将推出的4.18)上顺利运行。你可以在UE4虚幻市场找到该3dRudder插件。

我们遇到的问题
总体来说,这次集成还是非常顺利的。我们遇到的唯一的问题是移动视口摄像机,因为没有找到正确的文档或样本代码。所以,我们只能通过观察VR模式源代码来了解如何使用游戏手柄移动摄像机。

安装插件
最后,我们制作了一个视频,演示如何安装该插件以及将3dRudder与UE4配合使用是什么感觉。

首先展示的是如何在编辑器和VR模式中安装3dRudder插件,然后是如何在标准编辑器(从0:45开始)和VR模式下(从2:57开始)使用3dRudder在场景中移动。

虚幻引擎特别优惠

由于我们认为3dRudder确实能够提升UE4 VR编辑器的总体体验,所以我们很愿意为虚幻引擎开发者们提供优惠券,您可以花费99美元或99欧元从3dRudder专业网站购买3dRudder(原价179美元或179欧元),此优惠券的有效期为两周。请在www.3dRudderBusiness.com使用优惠码UE4SPECIAL3DRUDDER购买。