HumanoidRootPart randomly doesn't want to change CFrame

Helloo. I have a script that sets the HRP of the player’s character to their respective station spawnpoint. However, for some odd reason, it just randomly doesnt work?? Sometimes itll teleport the player, sometimes it just… doesnt.

Ready.OnServerEvent:Connect(function(player)
	print("Adding player to ready list... "..player.Name)
	local GamePlayer = GetPlayerData.GetGamePlayer(player)
	local Character = player.Character
	local hrp = Character:WaitForChild("HumanoidRootPart")

	--set station data
	local Station = CookingStations:WaitForChild(GamePlayer.Name)
	Station.Occupant.Value = player
	Station.Active.Value = true
	
--------issue here
	hrp.CFrame = Station.Spawn.CFrame	
	hrp.Anchored = false
	Character.Humanoid.WalkSpeed = 0
-------------

	table.insert(ReadyPlayers, player)
	if #ReadyPlayers == #players:GetChildren() then
		print("All players are ready!")
		BindStartRoundOne:Fire()
	end
end)

My only guess is that something weird is happening with the timing between moving the player and setting their character. Whenever a player selects their character in the waiting screen, it waits for the game start timer to stop before it changes the character. The reason I did that is obvious: the gui resets when the player character is changed. I thought it might be that the model wasn’t loading in on time, but Ready fires whenever the player’s camera is set to the new model’s HumanoidRootPart, so i’m not sure what it is.

Recording of it teleporting correctly

Recording of it not teleporting

Thanks for lendning a hand

Oh, here are the scripts (only necessary snippets) incase of need

Game in ServerScriptService, responsible for teleporting the character as well as changing their character once the game starts

--code here....
local ReadyPlayers = {}
local Ready = RE:WaitForChild("ImReady")

players.PlayerRemoving:Connect(function(player)
	for i, plr in pairs(ReadyPlayers) do
		if plr == player then
			table.remove(ReadyPlayers, i)
			break
		end
	end
end)

Ready.OnServerEvent:Connect(function(player)
	print("Adding player to ready list... "..player.Name)
	local GamePlayer = GetPlayerData.GetGamePlayer(player)
	local Character = player.Character
	local hrp = Character:WaitForChild("HumanoidRootPart")

	--set station data
	local Station = CookingStations:WaitForChild(GamePlayer.Name)
	Station.Occupant.Value = player
	Station.Active.Value = true
	

	hrp.CFrame = Station.Spawn.CFrame	
	hrp.Anchored = false
	Character.Humanoid.WalkSpeed = 0

	table.insert(ReadyPlayers, player)
	if #ReadyPlayers == #players:GetChildren() then
		print("All players are ready!")
		BindStartRoundOne:Fire()
	end
end)

-----code here....

for i, player in ipairs(players:GetChildren()) do
	local GamePlayer = GetPlayerData.GetGamePlayer(player)
	GetPlayerData.SetCharacter(player, GamePlayer.SelectedCharacter.Value)
end

Player in ServerScriptService, responsible for storing the player’s character selection

--------code here.....

local CC = RE:WaitForChild("ChangeCharacter")

CC.OnServerEvent:Connect(function(player, character)
	print("Changing player character.. "..player.Name.."'s character to "..character.Name)
	
	local GamePlayer = RS.GameData.Players
	for i, v in pairs(GamePlayer:GetChildren()) do
		if v.Value == player then
			GamePlayer = v
                        GamePlayer.SelectedCharacter.Value = character
			print("Setting player start character.. "..player.Name.." "..character.Name)
			break
		end
	end
	
	GivePlayerData:FireAllClients(player, character) --tell all clients this player changed their character and to update their gui
	
end)

------code here.....

CharDataScript in StarterPlayerScripts. Responsible for firing ready

--------------code here.....
ChangeCharacter.OnClientEvent:Connect(function(model)
	if model then
		print("I got the new model")
		local Camera = game.Workspace:WaitForChild("Camera")
		workspace.CurrentCamera.CameraSubject = model.Humanoid
		script.Switcharoo:Play()
		ImReady:FireServer()
	end
end)
-------------code here......

This is a great progress you have so far! Additionally, your code also looks nice and neat; as for the teleporting problem you are correct about changing the character last second causing the teleporting issue.

I will guarantee if you disable the physical character changing temporarily, the problem will suddenly fix itself.

I will not provide any code as it may break future features in your game, but I can tell you a potential solution. You unfortunately didn’t provide the part where the character actually gets replaced with the custom rigs, but that’s no problem.

So, since it sometimes does [THING] (teleporting) and sometimes doesn’t, the reason is because multiple scripts are running at once obviously. The first step you should take is to get some parity between each of the scripts & module scripts.

Within every custom rig, add an attribute or hidden part that signifies the loading is completely finished and the player is ready for teleportation. Change your code to hold off on teleportation until that attribute is satisfied or the hidden part exists.

This makes it so there shouldn’t be any different outcome with each instance.

With parity, you should now have a definite [THING] or no [THING], which in this case is teleporting the player. If they teleport every time, great, add a safeguard just in case. If they don’t teleport, experiment with different methods of bringing the player to a location as I doubt the problem resides in the custom rigs.

I hope this helps, sorry if I misinterpreted your code.

1 Like

Thanks a lot! I constantly worry about my code being yanderedev-core :sob:

I tried to do what you suggested by having a BoolValue inside the model called “Loaded”. Whenever the HumanoidRootPart existed, Loaded would be set to true. game would repeat task.wait() until Loaded was true. I will admit this may not be what you intended, but I am still learning and am not sure how to handle loading stuffs.

Since, in the game, the player can only change characters once (that being after the start timer is done), i will try having it set the player’s position inside of the ModuleScript instead. I will update on how that goes

1 Like

WHAT

1 Like

image
mkay… so this works
This should be fine because everyone is in a loading state until all the players are set up (and people who leave are removed from the ReadyPlayers table). I will still keep this topic open because I feel like this could be improved on

2 Likes

glad you found your own solution!

I do admit it was weird that it would be teleported back as seen in your clip, it was probably something to do with the rig.

as for efficiency, I wouldn’t worry about improving on the repeat loop unless it causes noticeable lag in the first build.

good luck on game development!

1 Like

Ill go ahead and mark it as the solution then for others. thanks a bunch!

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