I have this issue in my VR game where the hands lag behind when I move.
I’m using the camera cframe times the UserCFrame of the hands
Am I doing something wrong?
I have this issue in my VR game where the hands lag behind when I move.
I’m using the camera cframe times the UserCFrame of the hands
Am I doing something wrong?
You could create the hands on the server, but give network ownership to the Player, and on the Client use AlignPosition and AlignOrientation to move them around.
Are you using while loops that use wait()? If not, use some tweening function like Lerp to smooth it out.
It uses UserInputService for the UserCFrame. I learned about while loops a long time ago.
RenderStepped could be use instead of UserCFrame:Connect() (I think).
RunService.RenderStepped:Connect(function()
Hand.CFrame = UserCFrame
end)
If you don’t want to, it’s best to smooth out the lag.
To add to what everyone else has been saying, it is very important that you use the RunService rather than a while loop to get and update this data, as any frame missed will cause this ‘lag’ in your tracking.
I wrote these two simple scripts that acts as a great starting point based off my own VR code for updating VR data across the server.
The idea is that the client gets all the VR CFrames, aligns them in world-space, then tells the server these CFrames, so that the server can update the CFrames.
Here’s the local script, it simply gets the UserCFrames for the VR positions, calculates the world-space based off the CurrentCamera, positions the parts on the client, then sends those CFrames to the server to replicate. In theory, the client should update fast enough, that the server trying to reposition a part won’t do anything, but if it is a problem, you can just have the server send the data to the clients, then each individual client updates the user’s cframes. This approach would limit the server visibility (for things such as physics interactions) and could waste bandwidth, but would ensure there is 0 ‘lag’ on the client. (I wouldn’t recommend that approach as it would be more of a last scenario)
local RunService = game:GetService('RunService')
local VRService = game:GetService('VRService')
-- Change this to the RemoteEvent that updates the server
local RemoteEventToUpdate = nil
-- Change these three to your parts
local headPart = nil
local leftHandPart = nil
local rightHandPart = nil
-- Every Render Frame, run this code
RunService.RenderStepped:Connect(function()
if RunService:IsServer() then
warn("You cannot get User CFrames from the Server! Use remote events to update data.")
return
end
-- HeadScale is used to align the hands in world-space while accounting for avatar size
local HeadScale = workspace.CurrentCamera.HeadScale
-- The HMDs CFrame
local cfHMD = VRService:GetUserCFrame(Enum.UserCFrame.Head)
-- The Left Hand's CFrame
local cfLH = VRService:GetUserCFrame(Enum.UserCFrame.LeftHand)
-- The Right Hand's CFrame
local cfRH = VRService:GetUserCFrame(Enum.UserCFrame.RightHand)
-- Now, align them all in world-space
local Head = (workspace.CurrentCamera.CFrame*CFrame.new(cfHMD.p*HeadScale))*CFrame.fromEulerAnglesXYZ(cfHMD:ToEulerAnglesXYZ())
local LeftHand = (workspace.CurrentCamera.CFrame*CFrame.new(cfLH.p*HeadScale))*CFrame.fromEulerAnglesXYZ(cfLH:ToEulerAnglesXYZ()) * CFrame.Angles(math.rad(90), 0, 0)
local RightHand = (workspace.CurrentCamera.CFrame*CFrame.new(cfRH.p*HeadScale))*CFrame.fromEulerAnglesXYZ(cfRH:ToEulerAnglesXYZ()) * CFrame.Angles(math.rad(90), 0, 0)
-- Then, you can set your target parts to the CFrames
headPart:PivotTo(Head)
leftHandPart:PivotTo(LeftHand)
rightHandPart:PivotTo(RightHand)
-- Then to replicate, fire a remote with the part CFrame across the server
-- It is very important to note that firing a remote in a while loop can cause bandwidth issues, as RemoteEvents are optimized better for RenderSteps
RemoteEventToUpdate:FireServer({
["Head"] = Head,
["LeftHand"] = LeftHand,
["RightHand"] = RightHand
})
end)
Now, for the server script. All it does is it listens for a client to fire the specified RemoteEvent, then gets those parts to update from the server, and updates the parts CFrames to the ones that were provided from the client. You will need to change the GetPlayerParts(player)
function as it is specific to how your game functions. It probably is possible to pipe the part directly from the client, but that would probably use more bandwidth (serializing the part and data for the new CFrames), and I believe it’s better to give the server full authority over which parts should be updated.
-- Change this to the RemoteEvent that updates the server
local RemoteEventToUpdate = nil
local function GetPlayerParts(player)
-- TODO: Get the Head, LeftHand, and RightHand part from the player
return {
["HeadPart"] = nil,
["LeftHandPart"] = nil,
["RightHandPart"] = nil
}
end
RemoteEventToUpdate.OnServerEvent:Connect(function(player, data)
-- If any of the data is nil, don't do anything
if data["Head"] == nil or data["LeftHand"] == nil or data["RightHand"] == nil then return end
-- Get all the player's parts
local parts = GetPlayerParts(player)
-- If any of the parts are nil, don't do anything
if parts["HeadPart"] == nil or parts["LeftHandPart"] == nil or parts["RightHandPart"] == nil then return end
-- Update the Head
parts["HeadPart"]:PivotTo(data["Head"])
-- Update the LeftHand
parts["LeftHandPart"]:PivotTo(data["LeftHand"])
-- Update the RightHand
parts["RightHandPart"]:PivotTo(data["RightHand"])
end)
Before I end this off, I’d also like to point out that if you absolutely without a doubt, for some odd reason NEED to use a wait() or while loop in the body that updates your CFrames, I would look into coroutines, as they provide a way to execute a task on another thread in the same script.
There are lots of comments left in the code, so everything should be pretty straightforward, but let me know if you need any clarifications. Apologies in advance for any missing services or typos, haha. Good luck!
Wouldn’t this error anyway? You can’t use RenderStepped on server, only Heartbeat.
Apologies, my reference code was built around modules, pretty much just for visibility haha.
I didn’t use while loops…
RenderStepped did work though.
To add as to why it worked, is RenderStepped occurs on the render thread, using different hooks will cause visual lag.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.