保持Htc Vive头盔与手柄和人物位置的一致
头戴设备的位置关系
在4.11及以后版本中进行 VR 开发,要知道两件事
- 头戴设备有自己的一套坐标系,在进入 VR 模式时 Character 位置和头戴设备位置会有偏差
- 在现实世界中移动位置的时候, Character 位置不会随着移动
这是因为官方在4.11更新里特意处理了这种偏差,原话如下:
为头戴显示设备做的摄像机系统做了改进,丰富了功能并且更加好用。我们将当前激活的摄像机组件在引擎中做了一定的偏移来适配真实世界中头戴显示设备的偏移。这么做能让大家能够更加容易的计算 VR 头戴设备在世界中的位置,可以直接附属其他模型也更为准确。并简化大家 VR 游戏的控制计算。
所以为了防止在使用瞬移时位置不对,或者进行移动时出现穿墙等蛋疼的事情,就要消除这种偏差,使得 Character 自动保持和头戴设备的位置一致。
为了实现这一功能,首先需要一个组件去调整 Camera 和 Character 的位置,然后在 Tick 里面消除移动时候的 Camera 和 Character 的误差
我们使用一个默认的组件作为调整摄像机的组件:
USceneComponent * CameraAdjustComponent = CreateDefaultSubobject<USceneComponent>(TEXT("CameraAdjustComponent"));
CameraAdjustComponent->AttachTo(GetMesh());
Camera->AttachTo(CameraAdjustComponent);
然后在切换进入VR模式的时候:
UKismetSystemLibrary::ExecuteConsoleCommand(this, "stereo on", UGameplayStatics::GetPlayerController(this, 0));//启动头显
ShouldTrack = true;//在进入VR模式时才调整位置
FRotator HMDRotator;
USteamVRFunctionLibrary::GetTrackedDevicePositionAndOrientation(0, LastHMDLocation, HMDRotator);//追踪头显位置
LastHMDLocation.Z = 0;//我们不要垂直方向的值
CameraAdjustComponent->SetRelativeLocation(-location);//调整组件至相反位置,这样头显的位置就正好和Character位置一样
在Tick里更新的时候:
USteamVRFunctionLibrary::GetTrackedDevicePositionAndOrientation(0, CurrHMDLocation, HMDRotator);
FVector offset = CurrHMDLocation - LastHMDLocation;//获取偏移量
offset.Z = 0;
AddActorLocalOffset(offset);//使用SetLocation会使人物无法移动
CameraAdjustComponent->AddLocalOffset(-offset);
LastHMDLocation = CurrHMDLocation;
这样在游戏过程中不论是自己带着头盔移动还是使用按键移动人物, Camera 和 Character 的位置都始终在一起了,使用瞬移的时候也不会存在偏差。
手柄的位置关系
使用手柄最重要的就是 UMotionControllerComponent 的组件,有时候你可能会单独的把组件放入一个 Actor 里或是直接继承这个组件用于实现一些自定的功能。
要使手柄组件追踪的位置一致只需要将 UMotionControllerComponent 以 EAttachLocation::KeepWorldPosition 的方式 Attach 到你的 Camera 所在的父组件即可,比如 CameraAdjustComponent ,这样手柄和现实中以及你的头戴设备的对应关系就对了。也不用自己每一帧去手动更新 MotionController 的位置了。
LeftController->MotionController->AttachTo(CameraAdjustComponent, NAME_None, EAttachLocation::KeepWorldPosition);
RightController->MotionController->AttachTo(CameraAdjustComponent, NAME_None, EAttachLocation::KeepWorldPosition);