Camera glitching when I rotate the player

I want to implement custom characters + movement for a game.

  1. The camera - not the player - keeps glitching backwards when the player is rotated.
  2. There is a small delay on input and when the player moves. Why?

I have identified the problematic line. The majority of code is in two scripts:
One Local Script:

--Consts
local MAX_SPEED = 20
local ACCELERATION = 1
local FD_ACTION = "Forward"
local BD_ACTION = "Backward"
local LT_ACTION = "Left"
local RT_ACTION = "Right"
--Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")
--Locals
local player = Players.LocalPlayer
local character = workspace.Players:WaitForChild(player.Name)
local humanoid = character:WaitForChild("Humanoid")
local camera = workspace.Camera
local velocity = Vector3.zero
local armModel = game.ReplicatedStorage.Assets.Character.__ARM_MODEL__:Clone()
repeat wait() until player.Character
local shirt = player.Character:FindFirstChildWhichIsA("Shirt"):Clone()

camera:GetPropertyChangedSignal("CFrame"):Connect(function()
	local pitchX, pitchY, pitchZ = camera.CFrame:ToOrientation()
	game.ReplicatedStorage.Remotes.CameraChanged:FireServer(pitchX, pitchY, camera.CFrame.Position)
	armModel:PivotTo(CFrame.new(camera.CFrame.Position) * CFrame.Angles(0,pitchY, 0))
end)

RunService.Heartbeat:Connect(function(dTime)
	local keysDown = UserInputService:GetKeysPressed()
	for i,v in pairs(keysDown) do
		keysDown[i] = v.KeyCode
	end
	velocity = Vector3.zero
	if table.find(keysDown, Enum.KeyCode.W) then
		velocity -= Vector3.zAxis
	end
	if table.find(keysDown, Enum.KeyCode.A) then
		velocity -= Vector3.xAxis
	end
	if table.find(keysDown, Enum.KeyCode.S) then
		velocity += Vector3.zAxis

	end
	if table.find(keysDown, Enum.KeyCode.D) then
		velocity += Vector3.xAxis
	end
	velocity = velocity.Unit
	humanoid:Move(velocity, true)
end)
armModel.Parent = workspace
shirt.Parent = armModel

And one server side script:

--Services
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local InsertService = game:GetService("InsertService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
--Consts
local DEFAULT_CHARACTER = {13902494655, 13902489990, 13901896422, 13901862002} --pants, shirt, hair, face. Face and hair must be a model.
local BASE_CHARACTER_MODEL = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("Character"):WaitForChild("__DEFAULT__")
local CHARACTER_DATASTORE_KEY = "AashesGame0_Characters_76b5h"
--Locals
local characters = {}
local inventoryDatastore = DataStoreService:GetDataStore(CHARACTER_DATASTORE_KEY)

function GetCharacter(player)
	local success, character = pcall(function()
		return inventoryDatastore:GetAsync(player)
	end)
	if success and character then
		return character
	else 
		return DEFAULT_CHARACTER
	end
end

function LoadCharacter(charInfo, player)
	local char = BASE_CHARACTER_MODEL:Clone()
	char:TranslateBy(Vector3.new(4,0,0))
	char.Parent = workspace.Players
	char.Name = player
	local charFolder = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("Character")
	charFolder:WaitForChild("Pants"):FindFirstChild(charInfo[1]):Clone().Parent = char
	charFolder:WaitForChild("Shirts"):FindFirstChild(charInfo[2]):Clone().Parent = char
	charFolder:WaitForChild("Hair"):FindFirstChild(charInfo[3]):Clone().Parent = char
	charFolder:WaitForChild("Face"):FindFirstChild(charInfo[4]):Clone().Parent = char
	
	return char
end

Players.PlayerAdded:Connect(function(player)

	local charInfo = GetCharacter(player.Name)
	local charObj = LoadCharacter(charInfo, player.Name)
	for i,v in pairs(charObj:GetChildren()) do
		if v:IsA("BasePart") then
			v:SetNetworkOwnershipAuto(false)
			v:SetNetworkOwner(player)
		end
	end
	player.CharacterAdded:Connect(function(char)
		if not char.Parent then
			char:Destroy()
		end
		player.Character = charObj
		ReplicatedStorage.Remotes.ChangePlayerCharacter:FireClient(player)
	end)
end)

ReplicatedStorage.Remotes.CameraChanged.OnServerEvent:Connect(function(player, pitchX, pitchY)
	local char = workspace.Players:FindFirstChild(player.Name)
	if char then
		char.Head.Neck.C0 = CFrame.new(char.Head.Neck.C0.Position) * CFrame.Angles(pitchX, 0, 0)
		char.HumanoidRootPart.CFrame = CFrame.new(char.HumanoidRootPart.CFrame.Position) * CFrame.Angles(0, pitchY, 0)
	end
end)

The camera issue:


The player only glitches when it is pointed diagonally, not forwards, backwards or side to side. It always glitches if I move the camera while the player is moving :confused:

1 Like

I suggest using the RenderStepped method instead of Heartbeat, this should solve input lag brcause it activates every frame on the client instead of every physics frame on the server (server is slow). However, I haven’t yet figured out the camera issue.

This is bad practice, I suggest doing this instead since it waits for the character if it has not spawned in when you define the character variable.

local character = player.Character or player.CharacterAdded:Wait()

That makes sense, I’ll modify that. I think the camera issue is something to do with the humanoid:move being on the client but the rotation being on the server, but I really dont’t know :confused:

2 Likes

That didn’t work for the minor latency, but I did make a small change to prevent lag from slowing down the player:

RunService.RenderStepped:Connect(function(dTime)
	local keysDown = UserInputService:GetKeysPressed()
	for i,v in pairs(keysDown) do
		keysDown[i] = v.KeyCode
	end
	velocity = Vector3.zero
	if table.find(keysDown, Enum.KeyCode.W) then
		velocity -= Vector3.zAxis
	end
	if table.find(keysDown, Enum.KeyCode.A) then
		velocity -= Vector3.xAxis
	end
	if table.find(keysDown, Enum.KeyCode.S) then
		velocity += Vector3.zAxis

	end
	if table.find(keysDown, Enum.KeyCode.D) then
		velocity += Vector3.xAxis
	end
	velocity = velocity.Unit * SPEED * dTime
	humanoid:Move(velocity, true)
end)

Does anyone know how to fix this? Its kinda halted any further development in my game, and so any help would be appreciated :slight_smile:

I have figured it out. Effectively I have a client side character that doesn’t rotate and is invisible. This is the CameraSubject, and this is what humanoid:moves when you press a key. Then, the server model is updated with positional and rotational info when the player moves/has camera rotated. The only obvious downside to this is that players cannot collide with each other, which is very minor realistically speaking. This also solves the input lag for some reason, so I’m not complaining ツ

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.