Attempting to create Vive VR Pawn in C++

I was reading this: https://docs.unrealengine.com/latest/INT/Platforms/SteamVR/QuickStart/2/index.html
to understand how to add vive support to a project, with the intention of implementing it in C++ instead of BP.

Mind you that I am new to Unreal so some aspects of its architecture still don’t make complete sense to me (even after reading several docs in the website).

So this is what I did so far:

UCLASS()
class VRTEST_API AVRPlayer : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AVRPlayer();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
	
	UPROPERTY(EditAnywhere)
		UCameraComponent* camera;

	UPROPERTY(EditAnywhere)
		UShapeComponent* collider;

	UPROPERTY(EditAnywhere)
		class UMotionControllerComponent* leftController;

	UPROPERTY(EditAnywhere)
		UStaticMeshComponent* leftControllerMesh;

	UPROPERTY(EditAnywhere)
		class UMotionControllerComponent* rightController;

	UPROPERTY(EditAnywhere)
		UStaticMeshComponent* rightControllerMesh;
};


<cpp>

AVRPlayer::AVRPlayer() : APawn() {
	PrimaryActorTick.bCanEverTick = true;
	BaseEyeHeight = 0.;
	
	camera = CreateDefaultSubobject<UCameraComponent>(TEXT("HMD Camera"));
	camera->SetupAttachment(RootComponent);

	/*collider = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Collider"));
	collider->SetupAttachment(camera);
*/
	leftController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Left Controller"));
	leftController->SetupAttachment(RootComponent);
	leftController->Hand = EControllerHand::Left;
	leftControllerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh L"));
	leftControllerMesh->SetupAttachment(leftController);

	rightController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Right Controller"));
	rightController->SetupAttachment(RootComponent);
	rightController->Hand = EControllerHand::Right;
	rightControllerMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh R"));
	rightControllerMesh->SetupAttachment(rightController);
}

(notice I am not dealing with the collider yet)

My issue is with the hmd positioning. When I instantiate the pawn at 0,0,0 in the level, the camera shows up overlapping the ground (set at 0,0,0 too), which is what I’d expect.

When I hit play however, the camera ends up above ground level, which means when I put the hmd on, I have already an extra offset which is incorrect, in the z direction up.

I noticed that in the BP link they add one scene component as a child of the root scene component and they offset it by 110 down. But I have a couple issues with the example doing that:

  1. Why add a second component, if the root component in a pawn is already a scene component (i.e. the actor has a transform).
  2. Why offset it by 110? this seems completely arbitrary and the hmd should just be at 0, and it’s height be determined by the height at which it finds itself at runtime. This is why in my code I am not using a second scene component.

Also note that I am not using a player start. So the spawning at runtime happens wherever I dropped the VRPlayer pawn in the editor (0,0,0).

An interesting thing is that I somehow managed to get this to start at 0,0,0 once, but I do not know what did I touch to make that happen :confused: I would expect the code above to be enough.

Any thoughts?

Ok I figured it out. Since I am not setting the player for the pawn in code, when I start PIE it just assigns not sure what but the camera ends up shifted up (still not sure about the full rationale of this).

The point being, the time it had worked it was because from the editor, under the pawn settings, I had set Auto Possess Player to player 0.

I believe I can also do this in code via AutoPossessPlayer = EAutoReceiveInput::Player0;
But I decided to leave this setup step in the editor for now.

A separate issue is that if I do not assign a root component to the pawn in the constructor, the hierarchy seems to get messed up: the components actually end up being children of the camera even though my code makes them children of root. I think the camera is getting assigned to root somehow (my code is not assigning it). I understood that every scene actor had a default scene root component, which is why I was even calling the super constructor. But maybe I misunderstood.

So now I also make the root explicit, by assigning a USceneComponent, and attaching everything to that but for a capsule collider which I attach instead to the camera (my assumption being that the logical behavior is for the collider to move with the camera i.e. if the player crouches, so does the collider).