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();
}