Character has different position in server and client

  1. What do you want to achieve?

I have a Part, which freezes players when they touch it.

  1. What is the issue?

I get code from Quoteory. Here is his code.

Implementation : When player touches the part, character’s parts are anchored, server creates a ice-like Part, whose Cframe is set to character’s Cframe.

When I tested in Studio, the client looks like this:

The server looks like this:

There are two problems:

  • Major One: Client and server looks different. In Client, character is not in the Ice Part.
  • Miner One: The character hasn’t touche the part, but he is frozen. ( I didn’t realize this issue until I write this post)
  1. What solutions have you tried so far?

I searched on forum. I get the impression that this has something to do with physics engine in Roblox. But I fail to find further information.

I am new to Roblox, any instruction would be nice. Thx !

Code (I changed a little bit from the original one to suit my spec):

local Part = script.Parent

local FROZEN_LOCK = 2
local FROZEN_TIME = 2

local IceBlock = Instance.new("Part")
IceBlock.BrickColor = BrickColor.new("Baby blue")
IceBlock.Size = Vector3.new(5, 7, 5)
IceBlock.Transparency = 0.5
IceBlock.Anchored = true

local Frozen = {} -- we will use this to store all of our frozen characters

function isCharacterFrozen(character, frozenTable)
	if frozenTable[character] then
		return true
	end
	return false
end

function CharAnchor(Character, AnchorBool) -- anchor will be true or false
	for _, CharacterPart in pairs(Character:GetChildren()) do
		if CharacterPart:IsA("BasePart") then -- if the child is a basepart so we don't try to anchor scripts etc and get an error
			CharacterPart.Anchored = AnchorBool
		end
	end
end

function FreezeCharacter(Character)
	CharAnchor(Character, true) -- anchor the character
	local IceBlockClone = IceBlock:Clone()
	IceBlockClone.Parent = workspace
	IceBlockClone.CFrame = Character.PrimaryPart.CFrame -- move the IceBlock to the character

	Frozen[Character] = IceBlockClone -- index the character with the new IceBlock
end

function UnFreezeCharacter(Character)
	local IceBlock = Frozen[Character] -- Checks if the Character is frozen
	if IceBlock then 
		IceBlock:Destroy()
		CharAnchor(Character, false)
	end
end

function removeFrozenLock(Character)
	Frozen[Character] = nil
end

Part.Touched:Connect(function(hit)
	
	local hitParent = hit.Parent
	local humanoid = hitParent:FindFirstChildWhichIsA("Humanoid")

	if not humanoid then
		return
	end

	local isFrozen = isCharacterFrozen(hitParent, Frozen)
	if isFrozen then
		return
	end

	FreezeCharacter(hitParent)

	wait(FROZEN_TIME)
	
	UnFreezeCharacter(hitParent)

	wait(FROZEN_LOCK)
	removeFrozenLock(hitParent)
end)

1 Like

this problem should be an easy fix, after you make the ice, set the players position back to the ice.

2 Likes

You should probably freeze the player before you add in the ice block.

2 Likes

Firing the client with a remote event telling them to set their own position back to where the server sees them at works great for me

Client

Server

FreezeServer in ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local freezeEvent = ReplicatedStorage.FreezeEvent

local freezePart = Instance.new("Part")
freezePart.Size = Vector3.new(7, 13, 7)
freezePart.Anchored = true
freezePart.BrickColor = BrickColor.Blue()
freezePart.Transparency = .5

local frozenCharacters = {}

local function anchor(character, bool)
	for _, part in ipairs(character:GetChildren()) do
		if part:IsA("BasePart") then
			part.Anchored = bool
		end
	end
end

local function freeze(character)
	if not frozenCharacters[character] then
		frozenCharacters[character] = true
		local player = Players:GetPlayerFromCharacter(character)
		local cframe = character.PrimaryPart.CFrame
		freezeEvent:FireClient(player, cframe)
		anchor(character, true)
		local freezePart = freezePart:Clone()
		freezePart.CFrame = cframe
		freezePart.Name = character.Name .. "FreezePart"
		freezePart.Parent = workspace
	end
end

local function thaw(character)
	if frozenCharacters[character] then
		frozenCharacters[character] = nil
		local player = Players:GetPlayerFromCharacter(character)
		freezeEvent:FireClient(player)
		local freezePart = workspace:FindFirstChild(character.Name .. "FreezePart")
		if freezePart then freezePart:Destroy() end
		anchor(character, false)
	end
end


Players.PlayerAdded:Connect(function(player)
	local function onCharacterAdded(character)
		wait(12)
		freeze(character)
		wait(12)
		thaw(character)
	end
	onCharacterAdded(player.Character or player.CharacterAdded:Wait())
	player.CharacterAdded:Connect(onCharacterAdded)
end)

FreezeClient in StarterCharacterScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local freezeEvent = ReplicatedStorage:WaitForChild("FreezeEvent")

local character = script.Parent
local primaryPart = character.PrimaryPart

freezeEvent.OnClientEvent:Connect(function(cframe)
	character:SetPrimaryPartCFrame(cframe)	
end)

and a FreezeEvent RemoteEvent in ReplicatedStorage

Demo place file Freeze.rbxl (21.8 KB)
(freezes characters 12 seconds after they spawn, and then thaws them 12 seconds after)

Issues: the only issue I noticed is minor animation desyncage between server and client on freeze, but I don’t think it’s that big of an issue

I didn’t do a ton of testing so there are possibilities of bugs, if so just reply and ill fix them asap

6 Likes

Though the player being out of place off the ice shouldn’t really be much of a problem. The player still can’t move and they can’t abuse anything with it.

It’s not a security problem, it’s a visual one

The player appearing to be outside of the ice while frozen does not look good

Quoteory! Thank You!
You are so kind and helpful.

This is my first post, you help me twice :smiley:

I will try your solution when I am back home.

And thank everyone else. Roblox community is awesome!

2 Likes