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

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

The lookVectors are printing properly, however despite the lookVector changing, the head of the second player stays in the same position, which hopefully helps narrow down the location of issue?


I also noticed a strange animation jitter with the functioning head, which I think is something I can handle later and very likely related to (but not caused by) this other issue.

Information dump since I have yet to get a response. I had a very long conversation on Discord with another scripter and they ultimately couldn’t help me. This is very important to me. I’ve been trying to figure this out for days and the lack of progress is causing extreme anxiety and ruining my motivation for the project as a whole.
Part transparency for head-turning has been turned to 0 to display the difference between Player 1 and Player 2. Once again had to post the clip on YouTube because of size limitations: https://www.youtube.com/watch?v=2tfcBaeeL64
Some screenshots of output errors that likely aren’t the cause (I think the issue is in the CharacterIKs script)




And finally, reposting the code!!!

ServerScriptService - Look

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)

StarterPlayerScripts - Look

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)

StarterPlayerScripts - CharacterIKs

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

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()
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 = 0
	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)

I’m confused.

You said “aren’t the cause”…?

It looks to me like everything in that screen shot is the cause.

I have noticed anytime Roblox has a script error it stops the game from working properly.

Maybe turn off those other scripts until you can get one script at a time to work.

Definately fix all errors or you will keep getting lost.

2 Likes

I will definitely try to fix the errors ASAP for sure. I also went and sent a message to the person who originally made the tutorial and adjusted script (5uphi) and they said they’d take a look at it. Hopefully I can fix it soon haha

Could you put the characterik script into to cat model and get rid of the playeradded stuff? Might fix the head not found.

1 Like

I don’t know how to adjust the script to make way for such a change.

While talking to 5uphi I adjusted some scripts, this post has details on how so.

This is what it looks like right now:

The script adjusted for these changes was the CharacterIKs script, however it is still having issues on the second client as seen on the video linked.

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

local function CharacterAdded(character)
	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()
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 = 0.5
	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:WaitForChild("Head").Position - player:GetAttribute("LookVector") * 10
	end
end)

Hey there! After some testing, I think I’ve figured out the problem. I downloaded the file “Inverse_Kinematics_Dynamic_Weight.rbxl,” and it seems that when it’s in use, the other player’s character consistently looks down. The weird part is that it also shows on their screen that other players are looking down too.

I tried removing line 16 from the localscript “CharacterIKs,” and everything worked fine after that. I’ll share the Roblox place link below this message. Hope this helps with your urgent issue.

Best regards,
Bloxynet


Inverse_Kinematics_Dynamic_Weightfixed.rbxl (58.2 KB)

1 Like

The reason for this issue is quite straightforward. By removing line 16, we address a problem with the “Character Added” function. This function essentially gets stuck, waiting for the character to die before moving on to the next set of codes. Consequently, the “RenderStepped” function doesn’t run as intended because it’s essentially halted on the “Character Added” function from line 16.

If you were to insert a print statement within the “RenderStepped” function, you’d notice that it consistently prints for one player, while for another player, it doesn’t. In essence, removing line 16 resolves this bottleneck and ensures the smooth execution of subsequent code, mitigating the issue you encountered.

To make sure that the “ik” variable is destroyed when the character dies, it’s better to use a humanoid.died function instead of waiting for it to happen.

Feel free to reach out if you have any more questions or need further clarification.

2 Likes

OH MY GOD IT WORKS
I seriously couldn’t figure out the issue by myself but you really saved me and my workflow. I made a few changes to your script (such as the onDied like you suggested) and tested it on a proper server with two different accounts and the head-turning is perfect. You’re my hero for this, thank you so much!!!

1 Like

It’s great to have been of help! Best of luck with the continued development of your game. :blush:

Make sure to review my response as the solution. :white_check_mark: :wink:

1 Like

Of course!
and to any poor soul searching the internet for this oddly specific solution, this is the final script I ended up with. It probably isn’t the best, but it does the trick!

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

local function CharacterAdded(character)
	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

	local function onDied()
		ik:Destroy()
	end
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 = 0
	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:WaitForChild("Head").Position - player:GetAttribute("LookVector") * 10
		end
end)
1 Like

QUICK UPDATE TO ANYONE FOLLOWING THIS:
The head-turning will temporarily break if other players do not morph into the proper model. So I highly suggest forcing the player to automatically morph when they join the game, or figuring out how to fix that. (If you do figure it out, share those deets with me lol)

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