Oculus Rift Separate View
Overview
By default, using an Oculus Rift in Unreal Engine 4 affects the rotation responsible for both the players view and movement direction.
There are two main ways to change this:
- Creating a Player Camera Manager, Player Controller & GameMode using Blueprints.
- Creating a new Player Controller, Character & GameMode in C++.
The end results are similar - the players view and movement directions are separate - but the C++ version is more flexible.
Blueprints
- Create a Blueprint that based on PlayerCameraManager.
- In the Defaults tab, find "Follow Hmd Orientation" and set it to "true".
- Create a Blueprint that based on PlayerController.
- In the Defaults tab, find Player Camera Manager Class and set it to your PlayerCameraManager Blueprint.
- Create a Blueprint that based on GameMode.
- In the Defaults tab, find Default Controller Class and set it to your PlayerController Blueprint.
- Finally, under your levels World Settings, find GameMode Override and set it to your GameMode Blueprint.
C++
The C++ method is a more complex, but is also more flexible.
Your.Build.cs
Add HeadMountedDisplay to PublicDependencyModuleNames.
PublicDependencyModuleNames.AddRange(new string[] {
"Core",
"CoreUObject",
"Engine",
"InputCore",
"HeadMountedDisplay"
});
});
YourPlayerController.h
virtual void UpdateRotation(float DeltaTime) override;
UFUNCTION(BlueprintCallable, Category="Pawn")
FRotator GetViewRotation() const;
UFUNCTION(BlueprintCallable, Category="Pawn")
virtual void SetViewRotation(const FRotator& NewRotation);
virtual void SetControlRotation(const FRotator& NewRotation) override;
protected:
/**
* View & Movement direction are now separate.
* The controller rotation will determine which direction we will move.
* ViewRotation represents where we are looking.
*/
UPROPERTY()
FRotator ViewRotation;
YourPlayerController.cpp
// Make sure you include this!!
#include "IHeadMountedDisplay.h"
void AYourPlayerController::UpdateRotation(float DeltaTime)
{
// Calculate Delta to be applied on ViewRotation
FRotator DeltaRot(RotationInput);
FRotator NewControlRotation = GetControlRotation();
if (PlayerCameraManager)
{
PlayerCameraManager->ProcessViewRotation(DeltaTime, NewControlRotation, DeltaRot);
}
SetControlRotation(NewControlRotation);
if (!PlayerCameraManager || !PlayerCameraManager->bFollowHmdOrientation)
{
if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHeadTrackingAllowed())
{
FQuat HMDOrientation;
FVector HMDPosition;
// Disable bUpdateOnRT if using this method.
GEngine->HMDDevice->GetCurrentOrientationAndPosition(HMDOrientation, HMDPosition);
FRotator NewViewRotation = HMDOrientation.Rotator();
// Only keep the yaw component from the controller.
NewViewRotation.Yaw += NewControlRotation.Yaw;
SetViewRotation(NewViewRotation);
}
}
APawn* const P = GetPawnOrSpectator();
if (P)
{
P->FaceRotation(NewControlRotation, DeltaTime);
}
}
void AYourPlayerController::SetControlRotation(const FRotator& NewRotation)
{
ControlRotation = NewRotation;
// Anything that is overriding view rotation will need to
// call SetViewRotation() after SetControlRotation().
SetViewRotation(NewRotation);
if (RootComponent && RootComponent->bAbsoluteRotation)
{
RootComponent->SetWorldRotation(GetControlRotation());
}
}
void AYourPlayerController::SetViewRotation(const FRotator& NewRotation)
{
ViewRotation = NewRotation;
}
FRotator AYourPlayerController::GetViewRotation() const
{
return ViewRotation;
}
YourCharacter.h
public:
virtual FRotator GetViewRotation() const override;
YourCharacter.cpp
FRotator AYourCharacter::GetViewRotation() const
{
if (AYourPlayerController* MYPC = Cast<AYourPlayerController>(Controller))
{
return MYPC->GetViewRotation();
}
else if (Role < ROLE_Authority)
{
// check if being spectated
for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
APlayerController* PlayerController = *Iterator;
if (PlayerController && PlayerController->PlayerCameraManager->GetViewTargetPawn() == this)
{
return PlayerController->BlendedTargetViewRotation;
}
}
}
return GetActorRotation();
}
YourGameMode.cpp
AYourGameMode::AYourGameMode(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
DefaultPawnClass = AYourCharacter::StaticClass();
PlayerControllerClass = AYourPlayerController::StaticClass();
}