How would I freeze a player in mid air so they can finish loading?

In my game, I had a loading script that worked fine, except that it used anchoring to freeze them in midair. Roblox doesn’t replicate client-owned anchored parts, so the player would appear frozen indefinitely on the other clients.

I’m looking for a way to freeze them in midair until they are fully loaded. I’m also hoping to have this replicated onto the server. Or if there is a way to notify the server that the client is loaded without using remote functions that would solve this too. Thank you for the help!

If there is a problem with my script or anything you see that could be improved please tell me, thank you!

Here is my local script:

local loadEvent = game:GetService("ReplicatedStorage"):WaitForChild("Load")
local player = game:GetService("Players").LocalPlayer
local contentProvider = game:GetService("ContentProvider")
loadEvent.OnClientEvent:Connect(function(folderToLoad,anchorPlayer)
	spawn(function()
		contentProvider:PreloadAsync({folderToLoad})
	end)
	--this is where I would put the script that freezes the player
	while contentProvider.RequestQueueSize > 0 do
		wait(0.5)
	end
    -- this is where I would put the script that unfreezes the player
end)
5 Likes

Couldn’t you just anchor the humanoidrootpart? This doesn’t make the model break joints or such. Though I am unsure how effective this is.

I tried anchoring the humanoidrootpart and it produces the same results as anchoring the torso. I think this is because the humanoidrootpart is still client-owned, so anchoring it doesn’t replicate to the server.
Here is when I tried to anchor the humanoidrootpart:
Image from Gyazo

It seems like you have something client-sided unanchoring / not even using humanoidrootpart.

You should do what every other game does, make a box and teleport them to the box instead and when the loading is done teleport them back to the main game, they won’t be able to do much in a box.

You could not let their character load until they are loaded unless you are keen on just freezing the character

I was using humanoidrootpart and anchoring it. It was done from the client side, because I need them to be frozen in the air until they are loaded in fully, and I don’t want to use a remote function because that would be server-client-server. Is there any way I could make this all run on the client and still be replicated? Or any way I could have the client tell the server when it’s loaded in without opening up any doors for exploiters and errors?

This is being done after the character is loaded in, because it is a match that the player starts. When they start it I want to have them frozen in mid air until they are loaded. Sorry for any misunderstanding due to my poor phrasing of the question I’ll edit it right now. Do you know of any way I can either tell the server when the client is loaded in or have the anchoring replicate to the server?

I’ve seen it done this way before in other games, and I don’t want them moved to a box since that seems inefficient to me. I would like to have it all done client sided and telling the server when the client is loaded still involves many unwanted server-client-server functions. Do you know of any way I could make it so the client cleanly tells the server when it’s loaded in all the way?

Tomorrow when I wake up I will read through the new replies and try all of the suggested fixes. If there are any questions I can answer them tomorrow. Thank you for the help!

Please never use RequestQueueSize as a way of determining when the player has loaded, because it’s not meant to be used that way.

RequestQueueSize is an arbitrary reading of how many assets are left in the client’s download queue, it doesn’t determine if the client loaded. The game determines a client as loaded when the DataModel snapshot is replicated to them, so game.Loaded/:IsLoaded.

The waiting time can depend on a user’s internet as well as how long it takes to fetch, cache and download assets. For users with bad service, this means longer waiting times. The worst thing you can do in a game is to interrupt their gameplay with long loading screens.

The downloading of these assets can just be streamed in the background.

Downloading is a purely client-side task and don’t forget exploiters exist, so they can spoof when they “finish” downloading on the server. Relaying when they finish is something that has to be client-authoritative too because the server wouldn’t know. Client-authoritative systems, in most cases (but not all), are awful especially if involved in a critical system.

1 Like

Thank you for taking the help, how should I go about making sure the client is loaded before moving them to the map? The time I’m trying to move them is after the server creates a randomly generated map for two players to use. Should I use :isloaded to check if they are loaded in?

Oh, is this for map loading? Yeah definitely don’t use RequestQueueSize then, because that’s not going to indicate that the map replicated, only that assets are now downloading (images, animations, sounds, things that need to come from a CDN).

You could just put the map in ReplicatedStorage so it’s queued for the snapshot. The server will replicate things in ReplicatedStorage to the client so for the cost of some memory, the map’s already available to clients. You could also have the server just not allow players to spawn in until it builds the map plus a small intermission afterward.

I’ll be real with you chief, I don’t really think there isn’t really a good way of doing this. A complex and hacky solution might work but I don’t know how those developers do it. We just have little to no tools for determining when things replicate, let alone control over replication.

1 Like

Thank you for the fast response time! However I don’t think I can put this into replicated storage, because it is creating as a grid of tiles procedurally generated when two players agree to enter into a match. Is there a way to securely send information to the server using events such that an exploiter can’t falsely say they are loaded in?

1 Like

ouch
no

Loading is a purely client-sided task so it’d also have to be authoritative of telling the server when it has finished as well, and only the client would know when that is. Some ideas for security here:

  • How soon does the remote fire after the server loads a map in and asks clients to tell it when they’re finished? Does it seem unrealistically quick? Use tick() for fine point accuracy.

  • Does the client fire the remote ahead of time in a place where they shouldn’t be? Might be something shady going on there if the client tells the server it loaded when the server didn’t ask.

These are all kinds of considerations you can put forth. Ultimately though, the server does have to trust the client to an extent unless you just prevent the match from starting until a certain time after the server creates the map. Making a guess about when replication finishes and all.

2 Likes

Thank you, I will definitely try this tomorrow! I guess it was inevitable that I would need to patch up the holes exploiters can get through. I never thought of using the event against the exploiters in that way. Thank you!

1 Like