[URGENT] Head turning only properly applied to first player to join game


(ignore the child in the background my friends brother was in the room LOL)

image
image

EDIT: Marked title as “URGENT” because progress cannot be made on the game (more specifically, the game cannot be played multiplayer) without resolving this.

Try using a remote event to change SetAttribute (“LookVector”) in your local Look script.

1 Like

I don’t understand. Sorry, I’m not well versed in Luascript and followed a string of tutorials to get to this point. :sweat_smile: I searched up the documentation on remote events and it doesn’t look all too different from what the script already contains.

Sorry for the late response, I just noticed you were setting an attribute on line 7 of your local script and you need to use a server script to set attributes.

1 Like

Check out my following scripts to see the change I made. It probably wasn’t the best since I don’t fully understand how to edit such an advanced script. All the change did was make the head-turning a little more laggy/jittery, and still has the second player to join the game experience broken head turning.


I tried putting the full contents of the local “Look” script into the server “Look” script and it resulted in… this :skull:

Local “Look” script

local event = game.ReplicatedStorage.Look
local lookVector = Vector3.zero
local eventTime = -math.huge
local scheduleEvent = false

workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):Connect(function()
	--game.Players.LocalPlayer:SetAttribute("LookVector", workspace.CurrentCamera.CFrame.LookVector)
	if scheduleEvent == true then return end
	if workspace.CurrentCamera.CFrame.LookVector:Dot(lookVector) > 0.99 then return end
	local deltaTime = time() - eventTime
	if deltaTime > 0.1 then
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	else
		scheduleEvent = true
		task.wait(0.1 - deltaTime)
		scheduleEvent = false
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	end
end)

Server “Look” script

game.Players.PlayerAdded:Connect(function(player)
	player:SetAttribute("LookVector", Vector3.zero)
end)

game.ReplicatedStorage.Look.OnServerEvent:Connect(function(player, lookVector)
	player:SetAttribute("LookVector", lookVector.Unit)
end)

workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):Connect(function()
	game.Players.LocalPlayer:SetAttribute("LookVector", workspace.CurrentCamera.CFrame.LookVector)
end)

Also here’s “CharacterIKs” localscript which is related to the Look scripts but likely not this issue in particular.

local function PlayerAdded(player)
	local part = Instance.new("Part")
	part.Anchored = true
	part.CanCollide = false
	part.CanQuery = false
	part.CanTouch = false
	part.Transparency = 1
	part.Parent = workspace

	parts[player] = part

	if player.Character ~= nil then CharacterAdded(player.Character) end
	player.CharacterAdded:Connect(CharacterAdded)
	player.CharacterRemoving:Connect(CharacterRemoving)
end

local function PlayerRemoving(player)
	parts[player]:Destroy()
	parts[player] = nil
end

for i, player in game.Players:GetPlayers() do PlayerAdded(player) end
game.Players.PlayerAdded:Connect(PlayerAdded)
game.Players.PlayerRemoving:Connect(PlayerRemoving)

runService.RenderStepped:Connect(function(deltaTime)
	for player, part in parts do
		if player.Character == nil then continue end
		local ik = iks[player.Character]
		if ik ~= nil then ik.Weight = 1 + player:GetAttribute("LookVector"):Dot(player.Character.HumanoidRootPart.CFrame.LookVector) end
		part.Position = player.Character.Head.Position - player:GetAttribute("LookVector") * 10
	end
end)```

Just a question, why do you need server side script?

1 Like

I was following a tutorial that said it was required and I’m pretty sure it’s so other players can see the head turning as well?

This problem has not been solved yet!

Try just two scripts. Make changes on sever so everyone can see.

Server Script

--ServerScriptService
local runService = game:GetService("RunService")
local parts = {}
local iks = {}

local function CharacterAdded(character)
	task.wait()
	local ik = Instance.new("IKControl")
	ik.Type = Enum.IKControlType.LookAt
	ik.ChainRoot = character:WaitForChild("UpperTorso")
	ik.EndEffector= character:WaitForChild("Head")
	ik.Target = parts[game.Players:GetPlayerFromCharacter(character)]
	ik.Parent =  character.Humanoid
	iks[character] = ik
	character.Humanoid.Died:Wait() ik:Destroy()
end

local function CharacterRemoving(character)
	iks [character] = nil
end

local function PlayerAdded(player)
	local part = Instance.new("Part")

	part.Anchored = true
	part.CanCollide = false
	part.CanQuery = false
	part.CanTouch = false
	part.Transparency = 1
	part.Parent = workspace
	parts[player] = part
	if player.Character ~= nil then CharacterAdded(player.Character) end
	player.CharacterAdded:Connect(CharacterAdded)
	player.CharacterRemoving:Connect(CharacterRemoving)

end

local function PlayerRemoving(player)
	parts[player] :Destroy()
	parts[player] = nil
end

for i, player in game.Players:GetPlayers() do PlayerAdded(player) end

game.Players.PlayerAdded:Connect(PlayerAdded)
game.Players.PlayerRemoving:Connect(PlayerRemoving)

local function look()
		for player, part in parts do
		if player.Character == nil then continue end
		local ik = iks[player.Character]
		--if ik ~= nil then ik.Weight = 1 + player:GetAttribute("LookVector"):Dot(workspace.CurrentCamera.CFrame.LookVector) end
		if ik ~= nil then ik.Weight = 1 + player:GetAttribute("LookVector"):Dot(player.Character.HumanoidRootPart.CFrame.LookVector) end
		part.Position = player.Character.Head.Position - player:GetAttribute("LookVector") * 10	
	end
end

game.Players.PlayerAdded:Connect(function(player)
	player:SetAttribute("LookVector",Vector3.zero)
	game.ReplicatedStorage.ADDED:FireClient(player)
end)

game.Players.PlayerRemoving:Connect(function(player)

	game.ReplicatedStorage.REMOVING:FireClient(player)
end)

game.ReplicatedStorage.Look.OnServerEvent:Connect(function(player, lookVector)
	player:SetAttribute("LookVector",lookVector)
	
end)

game.ReplicatedStorage.Looking.OnServerEvent:Connect(look)

Local Script


--StarterPlayerScripts
local runService = game:GetService("RunService")
local event = game.ReplicatedStorage.Look
local lookVector = Vector3.zero
local eventTime = -math.huge
local scheduleEvent = false

workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):Connect(function()
	--game.Players.LocalPlayer:SetAttribute("LookVector", workspace.CurrentCamera.CFrame.LookVector)
	if scheduleEvent == true then return end
	if workspace.CurrentCamera.CFrame.LookVector:Dot(lookVector) > 0.99 then return end
	print("<99")
	local deltaTime = time() - eventTime
	if deltaTime > 0.1 then
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	else
		scheduleEvent = true
		task.wait(0.1 - deltaTime)
		scheduleEvent = false
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	end
end)

runService.RenderStepped:Connect(function(deltaTime)
	game.ReplicatedStorage.Looking:FireServer()
end)
1 Like

the part does not move around the head like its supposed to. this script does not function properly :frowning:
image

Oh no. Is this cat rig available and where do you set it to the player?

1 Like

No, client has NetworkOwnership over their character. So you don’t need Server script

1 Like

okay so i moved some stuff to a local script and disabled the old scripts and i … just dont know what im supposed to be doing rn…


localscript (i dont even know)

local runService = game:GetService("RunService")
local parts = {}
local iks = {}
local event = game.ReplicatedStorage.Look
local lookVector = Vector3.zero
local eventTime = -math.huge
local scheduleEvent = false

local function CharacterAdded(character)
	repeat wait() until "Head"

	local ik = Instance.new("IKControl")
	ik.Type = Enum.IKControlType.LookAt
	ik.ChainRoot = character:WaitForChild("Neck2")
	ik.EndEffector = character:WaitForChild("Head")
	ik.Target = parts[game.Players:GetPlayerFromCharacter(character)]
	ik.Parent = character.Humanoid
	iks[character] = ik

	character.Humanoid.Died:Wait() ik:Destroy() -- TEMP FIX
end

local function CharacterRemoving(character)
	iks[character] = nil
end


local function PlayerAdded(player)
	local part = Instance.new("Part")
	part.Anchored = true
	part.CanCollide = false
	part.CanQuery = false
	part.CanTouch = false
	part.Transparency = 1
	part.Parent = workspace

	parts[player] = part

	if player.Character ~= nil then CharacterAdded(player.Character) end
	player.CharacterAdded:Connect(CharacterAdded)
	player.CharacterRemoving:Connect(CharacterRemoving)
end

local function PlayerRemoving(player)
	parts[player]:Destroy()
	parts[player] = nil
end

for i, player in game.Players:GetPlayers() do PlayerAdded(player) end
game.Players.PlayerAdded:Connect(PlayerAdded)
game.Players.PlayerRemoving:Connect(PlayerRemoving)

runService.RenderStepped:Connect(function(deltaTime)
	for player, part in parts do
		if player.Character == nil then continue end
		local ik = iks[player.Character]
		if ik ~= nil then ik.Weight = 1 + player:GetAttribute("LookVector"):Dot(player.Character.HumanoidRootPart.CFrame.LookVector) end
		part.Position = player.Character.Head.Position - player:GetAttribute("LookVector") * 10
	end
end)

workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):Connect(function()
	game.Players.LocalPlayer:SetAttribute("LookVector", workspace.CurrentCamera.CFrame.LookVector)
	if scheduleEvent == true then return end
	if workspace.CurrentCamera.CFrame.LookVector:Dot(lookVector) > 0.99 then return end
	local deltaTime = time() - eventTime
	if deltaTime > 0.1 then
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	else
		scheduleEvent = true
		task.wait(0.1 - deltaTime)
		scheduleEvent = false
		eventTime = time()
		lookVector = workspace.CurrentCamera.CFrame.LookVector
		event:FireServer(lookVector)
	end
end)

please help. i have no clue what youre trying to tell me.

I’m not entirely sure what you’re trying to ask me. The rig is not available to the public because I made it myself and don’t want to lose it. However I’ll try to respond to what you’re asking?
The player applies the character by clicking a morph menu, which runs a local script

local ReplicatedStorage = game:GetService("ReplicatedStorage")

script.Parent.MouseButton1Click:Connect(function()
	ReplicatedStorage.MorphEvent:FireServer()
end)

and connects to this portion of a very long server-side character customization script, basically destroying the old player character and replacing it with the new model.

-- MORPH --

local Players = game:GetService("Players")
game.Players.PlayerAdded:Connect(function(plr)
	local player = plr
	game.ReplicatedStorage.MorphEvent.OnServerEvent:connect(function(plr)
		local oldCharacter = player.Character
		local newCharacter = FelineParent.Feline:Clone()

		newCharacter.HumanoidRootPart.Anchored = false
		newCharacter:SetPrimaryPartCFrame(oldCharacter.PrimaryPart.CFrame)

		player.Character = newCharacter
		newCharacter.Parent = workspace
	end)
end)

and if you’re asking how the model connects to the rig, the HumanoidRootPart connects to Torso1

Besides that, I’m not sure what you’re trying to ask me :sweat_smile:

I forgot to change the ik.ChainRoot back to neck2 I had to change it to work with just my character as I don’t have the cat rig.

ik.ChainRoot = character:WaitForChild("Neck2")

1 Like

And when I get to my PC I’ll check the part not moving.

1 Like

I’m sure I changed that on my end when I tried out your script, otherwise the heads wouldn’t turn at all for any players to join the game.
Note that the head-turning is functioning fine! But only for the first player to join the game. Everyone else’s head-turning won’t work. So when you test it, it needs to be with another player.

If you guys need further context to help understand the problem, here is some additional information.
I followed this tutorial by Suphi Kaner. It had some issues and I had to join the Discord to get the proper script, which can be found in this place file he provided for free: Inverse_Kinematics_Dynamic_Weight.rbxl (57.9 KB)

On my end I applied some of the math in reverse, since my model needed to move in opposition to the camera rather than following it, so if you’re having troubles applying it to your model / the normal Roblox avatar, please check the tutorial and compare it to my script. The change should be as simple as changing a “-” back to a “+”.

And again to clarify, the issue is occurring with two players, not one. When troubleshooting your solutions, you need to test it with another player on a Roblox server to see if it’s recreating itself.
Let me know if there’s more I need to clarify.

I added two print commands to your original server script.

They print as expected for 2 players.

game.Players.PlayerAdded:Connect(function(player)
	print("Player Added: look vector")
	player:SetAttribute("LookVector", Vector3.zero)
end)

game.ReplicatedStorage.Look.OnServerEvent:Connect(function(player, lookVector)
	print(player, "look vector", lookVector)
	player:SetAttribute("LookVector", lookVector.Unit)
end)

--workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):Connect(function()
--	print("server camera")
--	game.Players.LocalPlayer:SetAttribute("LookVector", workspace.CurrentCamera.CFrame.LookVector)
--end)

Try them and see if they work as expected.

If not, then add print commands in other places until you figure out where the values are not being sent or received.

Also, select the lookVector in the property window for each player and see if it is really being updated by the scripts.

1 Like

Ah my favorite troubleshooting technique, printing every other line until you get a response. I’ll try this and tell you what I get haha