ToScale "Teleport" Issue!

So I have this customcharacter and when he eats a fly he will get bigger and that is visible to every player in the game.

However there is an issue where the customcharacter “teleports” somewhere when eating the fly. I understand why the issue occurs because I have read this devforum post Scaling the character makes it "teleport".

But I don’t know how I can fix it since its a custom character and I want it to be visible for the whole server.

Here is a video of the issue and a photo of how the character is built:

character

Here is the code that I made to handle the size of the custom character:

Size.Changed:Connect(function()
	if Size.Value <= 200 then
		Humanoid.WalkSpeed = (defaultWalkSpeed - Size.Value/10)
		char:ScaleTo(1 + Size.Value/100)
						
		Humanoid.JumpPower = 0
		Points.Value = Size.Value
		PointsLabel.Text = Size.Value
	end		
end)

Any help would be greatly appreciated!

1 Like

Maybe you can try to save the original position before scaling the custom character then move it to that saved original position?

2 Likes

You got it right in the client? Do you know how to replicate the size change to server?

This is in a server script, but I can change it to do it to the localscript but yes I want to know how to replicate it to the server

First does it as localscript, see if it is working without the lag.

After localscript is working you will need a remoteEvent that is basic what you already have in the server.

Local like this to fire the event:

local ChangeEvent = ReplicatedStorage:WaitForChild("SizeChangeEvent")
ChangeEvent:FireServer(newSize)

Server like this

local remoteEvent = ReplicatedStorage:WaitForChild("SizeChangeEvent")
remoteEvent.OnServerEvent:Connect(function(player, newSize)
-- code to change size
end)

If the character has a humanoid, any changes made on the client should replicate automatically to the server.

I think if you just scale on the client, it should be ok.

Just tried it and it doesnt replicate to the server, when i scale on the client.

You mean like fireclient, change the scale and fire back the server to change the scale again? Because that doesn’t work since it also “teleports”

What you mean by teleport is a lag that happens when you try to use a Serverscript to change humanoid scale. To get rid of the lag you should scale with a Localscript.

The first localscript that change the humanoid scale and does fireServer().

The server script does a FireAllClients() passing the player and scale

The second localscript receives the player, scale, and update if needed.

All humanoid.Scale changes are done with a Localscript. The local player by the 1st script and all the other connected players by the second script.

It has always been the rule, that anything applied to the character would replicate, but I haven’t tested it with new things like the Scale property. Sorry for the misleading advice.

Finally had the time to do the code:

This is the local script, it has all function no need to another script I am using the StaterCharacterScripts folder:

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")


local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale") -- This event is the broadcast

-- This event get the broadcast of all players name and scale
local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale")
	remoteEvent.OnClientEvent:Connect(function(playerName, scaleValue)
	-- print("Client Received GrowScale event on the client with playerName: " .. playerName .. " and scale: " .. scaleValue)
	if game.Players.LocalPlayer.Name ~= playerName then
		local Players = game:GetService("Players")
		local player = Players:FindFirstChild(playerName)		
		if player then			
			--print("Player found: " .. player. Name)
			local scaleCharacter = player. Character
			scaleCharacter:ScaleTo(scaleValue) -- Change the scale for other players in the client
		else
			print("Player not found")
		end
	end
end)

-- This function broadcast to server the player name and model scale
function fireGrowScale (scaleValue)
	local playerName = game.Players.LocalPlayer.Name
	remoteEvent:FireServer(playerName, scaleValue)
end

-- This loop increase the player size if the player step on ice
while wait(1) do
	if humanoid.FloorMaterial == Enum.Material.Ice then
		print("Grow")
		local growTo = character:GetScale()+0.01
		character:ScaleTo(growTo) -- Change scale
		fireGrowScale(growTo) -- Broadcast scale
	end
end


Now the server script:

local remoteEvent = Instance.new("RemoteEvent")
remoteEvent.Name = "GrowScale"
remoteEvent.Parent = game.ReplicatedStorage

remoteEvent.OnServerEvent:Connect(function(player, playerName, scaleValue)
	-- print(player.Name .. " triggered the GrowScale event with playerName: " .. playerName .. " and scale: " .. scaleValue)	
	remoteEvent:FireAllClients(playerName, scaleValue)
end)

I did some tests and the scale propagate fine. If you need extra help to adapt to your code you can ask.

1 Like

So In my existing script i should fire to the client, change the size client sided, fire back to the server and make it fire all clients?? sorry i don’t really understand lol. The script that i showed is part of my “PlayerHandler” server script. What should i do from there… Fire all clients? And why the check for if the humanoid is walking on ice?

Btw thanks for the help much appreciated!

So sorry. It was just an example of fully functional scale propagation. Let me edit your code.

This is local-script. But I dont know how you initiate the Size variable.

-- This is a localscript

local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale") -- Broadcast event


-- This will tell the server the Name of the player and his scale

function fireGrowScale (playerName,scaleValue)	
	remoteEvent:FireServer(playerName, scaleValue)
end

-- This receive the scale of other players and update local

local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale")
remoteEvent.OnClientEvent:Connect(function(playerName, scaleValue)	
	if game.Players.LocalPlayer.Name ~= playerName then
		local Players = game:GetService("Players")
		-- Find the player, from the name sent by server
		local player = Players:FindFirstChild(playerName)		
		if player then
			local scaleCharacter = player. Character
			-- Set scale that was passed by the server
			scaleCharacter:ScaleTo(scaleValue) 
		end
	end
end)


-- Must be localscript code :
Size.Changed:Connect(function()
	if Size.Value <= 200 then
		Humanoid.WalkSpeed = (defaultWalkSpeed - Size.Value/10)
		char:ScaleTo(1 + Size.Value/100)	
		-- Get the Playername
		local playerNameToSend = game.Players.LocalPlayer.Name
		-- Tell the server Player and Scale
		fireGrowScale(playerNameToSend, char:GetScale())
		
		Humanoid.JumpPower = 0
		Points.Value = Size.Value
		PointsLabel.Text = Size.Value
	end		
end)

You need to add this script inside ServerScriptService folder:

local remoteEvent = Instance.new("RemoteEvent")
remoteEvent.Name = "GrowScale"
remoteEvent.Parent = game.ReplicatedStorage

remoteEvent.OnServerEvent:Connect(function(player, playerName, scaleValue)
	-- print(player.Name .. " triggered the GrowScale event with playerName: " .. playerName .. " and scale: " .. scaleValue)	
	remoteEvent:FireAllClients(playerName, scaleValue)
end)

You must understand that the event that trigger the character size increase must be local.

So if i understnad correctly, I should add this code into my server script:

local remoteEvent = Instance.new("RemoteEvent")
remoteEvent.Name = "GrowScale"
remoteEvent.Parent = game.ReplicatedStorage

remoteEvent.OnServerEvent:Connect(function(player, playerName, scaleValue)
	-- print(player.Name .. " triggered the GrowScale event with playerName: " .. playerName .. " and scale: " .. scaleValue)	
	remoteEvent:FireAllClients(playerName, scaleValue)
end)

Then create a new local script with this code

-- This is a localscript

local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale") -- Broadcast event


-- This will tell the server the Name of the player and his scale

function fireGrowScale (playerName,scaleValue)	
	remoteEvent:FireServer(playerName, scaleValue)
end

-- This receive the scale of other players and update local

local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale")
remoteEvent.OnClientEvent:Connect(function(playerName, scaleValue)	
	if game.Players.LocalPlayer.Name ~= playerName then
		local Players = game:GetService("Players")
		-- Find the player, from the name sent by server
		local player = Players:FindFirstChild(playerName)		
		if player then
			local scaleCharacter = player. Character
			-- Set scale that was passed by the server
			scaleCharacter:ScaleTo(scaleValue) 
		end
	end
end)


-- Must be localscript code :
Size.Changed:Connect(function()
	if Size.Value <= 200 then
		Humanoid.WalkSpeed = (defaultWalkSpeed - Size.Value/10)
		char:ScaleTo(1 + Size.Value/100)	
		-- Get the Playername
		local playerNameToSend = game.Players.LocalPlayer.Name
		-- Tell the server Player and Scale
		fireGrowScale(playerNameToSend, char:GetScale())
		
		Humanoid.JumpPower = 0
		Points.Value = Size.Value
		PointsLabel.Text = Size.Value
	end		
end)

And then in the server when the size change is supposed to be initiated i should fireclient?

Btw this is how i have the size variable:


Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		local plr = game:GetService("Players"):GetPlayerFromCharacter(char)
		local leaderstats = plr:WaitForChild("leaderstats")
		local Size = leaderstats:WaitForChild("Size")

--Here in between code for something else

Size.Changed:Connect(function()
			if Size.Value <= 200 then
				Humanoid.WalkSpeed = (defaultWalkSpeed - Size.Value / 10)
				char:ScaleTo(1 + Size.Value / 100)
			end

			Humanoid.JumpPower = 0
			Points.Value = Size.Value
			PointsLabel.Text = Size.Value
		end)

--Rest of the code

Or do i need to change that piece of code and do it in a local script and from there fire server?

You got wrong. The problem is this you using a lot of server code, this will lag. You need to move your logic to client side(aka localscripts).

There is a problem now with Size. When the character eats you use a localscript to trigger the server? Or it just all server scripts?

Had another ideia. Is not the best solution, dono if gonna work. But you can try:

Change the server script to this:

local remoteFire = Instance.new("RemoteEvent")

remoteFire.Name = "GrowScale"
remoteFire.Parent = game.ReplicatedStorage

Size.Changed:Connect(function()	
	remoteFire:FireAllClients(Size.Value,char)
end)

Now create a new localscript inside StarterPlayer:

local remoteEvent = game.ReplicatedStorage:WaitForChild("GrowScale")

remoteEvent.OnClientEvent:Connect(function(theSize, theChar)
	print("Got char:",theChar)
	print("Got size:",theSize)
	if theSize <= 200 then
		theChar:ScaleTo(1 + theSize/100)
	end
end)

Not the correct solution, but moving the ScaleTo to localscript, may be a solution.

1 Like

The character killing and eating are in the server script. I made a max eat dist and Fov function and it just loop through the players and all the flies and checks how close the distance is between the fly/enemyplayer and the player and if its less than the eatDist and in the FOV.

Ok. There is not localscript when character touch part as I was expecting. Please try the “another ideia” code just to see if lag goes away.