VR Movement doesn't move in the direction the camera is looking in

So I’ve been messing around with VR scripts again, and I’ve come across this really annoying issue with the camera.

I have a custom camera script that rotates the camera left and right depending on the thumbstick, and it only moves in the relative direction the theta is facing, but doesn’t account for where the camera lookvector is.

Video of the phenomenon happening:

Here’s my camera script incase it has anything to do with this:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local VRService = game:GetService("VRService")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer

local Bindables = ReplicatedStorage:WaitForChild("Bindables")
local UpdateHands = Bindables:WaitForChild("UpdateHands")

local USettings = UserSettings()
local UserGameSettings = USettings.GameSettings

local CurrentCamera = workspace.CurrentCamera

local Scriptable = Enum.CameraType.Scriptable
local Thumbstick = Enum.KeyCode.Thumbstick2
local Camera = Enum.RenderPriority.Camera
local UserHead = Enum.UserCFrame.Head

local CFAng = CFrame.Angles
local CFNew = CFrame.new

local V3New = Vector3.new

local rad = math.rad

local Turning, Theta = 0, 0

UserInputService.InputChanged:Connect(function(Input)
	if Input.KeyCode == Thumbstick then
		Turning = Input.Position.X
	end
end)

RunService:BindToRenderStep("CameraMovement", Camera.Value + 1, function(dT)
	if Turning > .25 or Turning < -.25 then
		local Scale = dT * 60
		Theta = Theta - ((Turning * (UserGameSettings.MouseSensitivity * 3)) * Scale)
	end
	
	local Character = Player.Character
	
	local RootPart = Character and (Character.PrimaryPart or Character:FindFirstChild("HumanoidRootPart")) or nil
	local Humanoid = Character and Character:FindFirstChild("Humanoid") or nil
	
	if Humanoid and RootPart then
		Humanoid.AutoRotate = false
		
		local HeadCF = VRService:GetUserCFrame(UserHead)
		local CamHeadCF = CurrentCamera.CFrame * HeadCF
		
		local CamHeadLV = CamHeadCF.LookVector
		local PosToUse = V3New(CamHeadLV.X, 0, CamHeadLV.Z)
		
		CurrentCamera.CFrame = CFNew(RootPart.Position + V3New(0, Humanoid.HipHeight)) * CFAng(0, rad(Theta), 0)
		RootPart.CFrame = CFNew(RootPart.Position, RootPart.Position + PosToUse)-- * CFAng(0, rad(Theta), 0)
	end
	
	UpdateHands:Fire()
end)

warn("CameraHandler.Init")

Any help is appreciated.

2 Likes

Why not just set the root CFrame to:
YawAngles + root.Position?
And also the camera to
FullAngles + (root.Position + <0, HipHeight, 0>)
Where both Yaw and Full Angles include the position offsets from headset movement, and the respective angle data.

What I’ve done in the past:
(Make sure to call recenter in case you put it on again)

HeadOffset = VRService:GetUserCFrame(UserHead)
Turned = HeadOffset * CFrame.Angles(0, yaw, 0)

root.CFrame = CFrame.new(
    root.Position, 
    root.Position
    + (Turned.LookVector * Vector3.new(1,0,1)).Unit
)
Camera.CFrame = Turned + (root.Position + offset)

Do note that i did not account for somehow exactly looking at <0,-1,0> or <0,1,0> in my code. You could fix that by just choosing one of the angles close to it.

4 Likes

Could you write a basic outline on what you mean?

Updated it just now so it should show an example

1 Like

While your code is good, there are a few things unexplained like what yaw should be connected to and what offset is. Also, one thing I’ve noticed is that the character is moving in the direction of the camera, it isn’t accounting for where the headset is looking. If your code is correcting this and I missed it, my apologies, I am tired.

My code solves all those issues and the yaw is just your theta basically, with offset being the hipheight I guess.
The way this code works is by taking the relative offset of the headset (which is based on its displacement from the “centered” state) and adjusting it in a way that makes it usable to both the camera and root part.
It is a very simple way of doing whatever you were writing out as well.

On a side note, I am working on a VR Module to make it easier for developers to interact with VR Elements by binding inputs and having an OnUpdate process with device data in both local and global spaces (as well as having adjustable height and scale properties).

2 Likes

Thanks for your help. The code now works with ease.

Don’t forget to check for the .Unit thing also, while it is very rare it can be possible. Might cause players to explode out of existance. This will happen when the length (Magnitude) of that vector is 0 before applying .Unit. Also I will update my post tomorrow with a WIP version of the module in case you would like to try it.

1 Like
1 Like