HTC Vive motion controller offset for some reason

Hello. I recently I started working with VR using HTC Vive. I have done some coding. All of it works but I am having just one problem for some reason. My motion controller, after starting game, starts at my head. And its tracked from there. For whatever reason there is this offset which should be there. The code I have written is below. Require help to fix this.

    //VRTestCharacter.h
    UCLASS()
    class OCEANPROJECT_API AVRTestCharacter : public ACharacter
    {
    	GENERATED_BODY()
    
    public:
    	
    	// Sets default values for this character's properties
    	AVRTestCharacter();
    
    	// 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;
    
    	UFUNCTION()
    		void MoveForward(float Value);
    
    	UFUNCTION()
    		void MoveRight(float Value);
    
    	UFUNCTION()
    		void StartJump();
    
    	UFUNCTION()
    		void StopJump();
    
    	UFUNCTION()
    		void PickObject();
    
    	UFUNCTION()
    		void Right_PickObject(float Value);
    	UFUNCTION()
    		void Left_PickObject(float Value);
    
    	UPROPERTY(VisibleAnywhere)
    		bool bObjectInRightHand;
    	UPROPERTY(VisibleAnywhere)
    		bool bObjectInLeftHand;
    	UPROPERTY(VisibleAnywhere)
    		AActor* LeftGrabbedActor;
    	UPROPERTY(VisibleAnywhere)
    		AActor* RightGrabbedActor;
    
    	UPROPERTY(VisibleAnywhere)
    		UCameraComponent* FPCameraComponent;
    
    	UPROPERTY(BlueprintReadWrite, EditAnywhere)
    		UStaticMeshComponent* MeshRight;
    
    	//Components required for motion controllers. Static meshes are used as place holders for hands till the skeletal meshes arnt avaiable
    	UPROPERTY(VisibleAnywhere)
    		UMotionControllerComponent* LeftHand;
    	UPROPERTY(VisibleAnywhere)
    		UMotionControllerComponent* RightHand;
    	UPROPERTY(VisibleAnywhere)
    		UStaticMeshComponent* RHMesh;
    	UPROPERTY(VisibleAnywhere)
    		UStaticMeshComponent* LHMesh;
    	UPROPERTY(VisibleAnywhere)
    		USkeletalMeshComponent* RHSkeletalMesh;
    	UPROPERTY(VisibleAnywhere)
    		USkeletalMeshComponent* LHSkeletalMesh;
    	UPROPERTY(VisibleAnywhere)
    		UArrowComponent* RHArrow;
    	UPROPERTY(VisibleAnywhere)
    		UArrowComponent* LHArrow;
    	UPROPERTY(VisibleAnywhere)
    		USteamVRChaperoneComponent* SteamVRChaperone;
    
    	UPROPERTY(BlueprintAssignable, Category = "Delegates")
    		FWhenClicked ClickedIt;
    };

And constructor is:

//VRTestCharacter.cpp

AVRTestCharacter::AVRTestCharacter()
{
	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	bObjectInRightHand = false;
	bObjectInLeftHand = false;
	LeftGrabbedActor = NULL;
	RightGrabbedActor = NULL;


	FPCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FPCamera"));
	FPCameraComponent->AttachToComponent(GetCapsuleComponent(), FAttachmentTransformRules::KeepWorldTransform);

	FPCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
	FPCameraComponent->bUsePawnControlRotation = true;
	SteamVRChaperone = CreateDefaultSubobject<USteamVRChaperoneComponent>(TEXT("SteamChaperone"));
	/*FPMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FPMESH"));
	FPMesh->SetOnlyOwnerSee(true);
	FPMesh->AttachTo(FPCameraComponent);
	FPMesh->bCastDynamicShadow = false;
	FPMesh->CastShadow = false;*/
	//GetMesh()->SetOwnerNoSee(true);
	//MeshRight = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshRight"));

	//Creating components for motion controller
	LeftHand = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("LeftHand"));
	RightHand = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("RightHand"));
	RHMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RHMesh"));
	LHMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LHMesh"));
	RHSkeletalMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("RHSkeletalMesh"));
	LHSkeletalMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("LHSkeletalMesh"));
	RHArrow = CreateDefaultSubobject<UArrowComponent>(TEXT("RHArrow"));
	LHArrow = CreateDefaultSubobject<UArrowComponent>(TEXT("LHArrow"));

	//Attaching Motion controller component to proper roots
	RightHand->AttachToComponent(FPCameraComponent, FAttachmentTransformRules::KeepWorldTransform);
	LeftHand->AttachToComponent(FPCameraComponent, FAttachmentTransformRules::KeepWorldTransform);
	LHMesh->AttachToComponent(LeftHand, FAttachmentTransformRules::KeepWorldTransform);
	LHSkeletalMesh->AttachToComponent(LeftHand, FAttachmentTransformRules::KeepWorldTransform);
	LHArrow->AttachToComponent(LHMesh, FAttachmentTransformRules::KeepWorldTransform);
	RHMesh->AttachToComponent(RightHand, FAttachmentTransformRules::KeepWorldTransform);
	RHSkeletalMesh->AttachToComponent(RightHand, FAttachmentTransformRules::KeepWorldTransform);
	RHArrow->AttachToComponent(RHMesh, FAttachmentTransformRules::KeepWorldTransform);

	RightHand->Hand = EControllerHand::Right;
	LeftHand->Hand = EControllerHand::Left;

}

Any help will be much appreciated.

Regards

EDIT: This issue is not faced when setting up motion controllers in BP.

Why are you giving the camera an offset on the Z-Axis?

Vive uses absolute position, so you should always keep it at the floor (so 0), since it will give an absolute position in relation to that.

Unless you’d like to give it an offset, e.g. because you want the head to be at a certain position, like in a seat or something, but then you should have an empty parent-container that has the offset and have the HMD have a position of 0,0,0 within that container.

As for your controllers: why are you attaching them to your HMD? This will of course make an offset depending on your HMDs position. Just attach them to root and that’s all you need to do, no need to attach to HMD.

I see that does make sense. I also found a VR example project that did what you are saying. I have tested it out and now its working fine. Thanks for your help.

Nice to hear it worked, thanks :slight_smile: