Tweening doesn't update the server

I’m making a system the allows you to knock over, and vault pallets.

I’ve came across an issue:

When the player climbs over the pallet, it anchors their character and tweens the Humanoid Root Part, that’s not the issue though, the issue is after the tween or tween(s) finish (for a split second) it sends the player back to the server’s position (mind you this only happens on the other clients not the player vaulting’s client).

I should also clarify, the player activates a proximityprompt which goes to the server and the server
Fires all the clients so its proximity prompt > server> all clients

all you really need to know about the server is this

TweenReplication:FireAllClients(plr, plrHumRoot, TweenOrder, playerAnimation.Animation.AnimationId, self.pallet)

Heres the client script though

local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local TweenReplication = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("PalletReplication"):WaitForChild("TweenReplication")

local lockInfo = TweenInfo.new(0.3, Enum.EasingStyle.Sine)

local myPlayer = game.Players.LocalPlayer


--THE FUNCTIONS


local function LoadTrack(animationId, animator)
	if animationId then
		local animation = Instance.new("Animation")
		animation.AnimationId = tostring(animationId)

		return animator:LoadAnimation(animation)
	end
end

local function ModelCollision(model, bool)
	for _, part in pairs(model:GetDescendants()) do
		if part:IsA("BasePart") and part.Transparency ~= 1 then
			part.CanCollide = bool
		end
	end
end

local function SetAllPrompts(bool)
	for i, prompt in pairs(game.Workspace:GetDescendants()) do
		if prompt:IsA("ProximityPrompt") and prompt:GetAttribute("Pallet") then
			prompt.Enabled = bool
		end
	end
end

local function CheckSprintAttribute(hum)
	if hum:GetAttribute("Sprint") and hum:GetAttribute("Sprint") == true then
		return true
	else
		return false
	end
end

local function SetPlayerMovement(bool, playerTurn, hum, humRoot)
	playerTurn.Enabled = bool

	if bool == false then
		hum.WalkSpeed = 0
		humRoot.Anchored = true
	else
		hum.WalkSpeed = 13
		humRoot.Anchored = false
	end
end


--TWEEN REPLICATION EVENT


TweenReplication.OnClientEvent:Connect(function (plr, targetedPart, targetCFrame, animationId, model)
	local char = plr.Character or plr.CharacterAdded:Wait()

	local hum = char:WaitForChild("Humanoid")
	local humRoot = char:WaitForChild("HumanoidRootPart")

	local playerTurn = char:WaitForChild("SetupScripts"):WaitForChild("PlayerTurn")
	local animator = hum:WaitForChild("Animator")

	local PalletBarrier = model:FindFirstChild("PalletBarrier")

	if PalletBarrier then
		PalletBarrier.CanCollide = false
	end

	local track = LoadTrack(animationId, animator)

	if typeof(targetCFrame) == "CFrame" then -- this happens when the player knocks over the pallet

		SetPlayerMovement(false, playerTurn, hum, humRoot)

		if plr == myPlayer then
			ModelCollision(model, false)
		end

		local tween = TweenService:Create(targetedPart, lockInfo, {CFrame = targetCFrame})

		tween:Play() --this tween locks the player in place
		task.wait(0.1)

		track:Play()

		task.wait(0.5)
		PalletBarrier.CanCollide = true

		SetPlayerMovement(true, playerTurn, hum, humRoot)

		if plr == myPlayer then
			ModelCollision(model, true)
		end

	else -- this happens when the player vaults the pallet
		if plr == myPlayer then
			SetAllPrompts(false)
			ModelCollision(model, false)
		end
		SetPlayerMovement(false, playerTurn, hum, humRoot)

		track:Play()
		track:AdjustSpeed(0.4)

		for i, theCFrame in pairs(targetCFrame) do
			if i == 1 then -- 1st tween locks plr in place, 2nd tween moves plr over pallet
				local tween = TweenService:Create(targetedPart, TweenInfo.new(0.6, Enum.EasingStyle.Sine), {CFrame = theCFrame})
				tween:Play()
				tween.Completed:Wait()
			else
				local tween = TweenService:Create(targetedPart, TweenInfo.new(1.5, Enum.EasingStyle.Sine), {CFrame = theCFrame})
				tween:Play()
				tween.Completed:Wait()
			end
		end

		if plr == myPlayer then
			ModelCollision(model, true)
		end
		SetPlayerMovement(true, playerTurn, hum, humRoot)
		PalletBarrier.CanCollide = true

		task.wait(0.2)
		if plr == myPlayer then
			TweenReplication:FireServer() -- all this does is re-enable the prompts for the server
			SetAllPrompts(true)
		end
	end

end)

Example Video of what’s happening:


if you didn’t notice its at the end of the vault when the players position gets set back

Larger code blocks are done with triple backticks (```) on the inside and outside of the code.

```
-- your code here
```

Since it’s quite tough to read without formatting, I don’t have an answer for you, but I would like to mention the existence of BasePart:SetNetworkOwner(), which could be a (cautious) solution to a similar problem.

1 Like

thank you, sorry i usually format it like said but for some reason i can’t find the button for it?

i tried using network ownership but it didn’t change, i’ve just added a video to the post

Using animation.Stopped and manually stopping the animation with fade time 0 and repositioning may help.


Also here’s a video on what suphi’s done to tween smoothly and effectively.

STARTS AT: 18 : 25

1 Like

this seems like it might be the solution! I’ll check out the video and get back to you guys on it.

works perfectly, customized it to sequence a table of tweens and play them in order, works perfectly though, thank you!!!

–my adjusted script

local module = {}

local event = game.ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("Optimization"):WaitForChild("LocalTween")
local threads = {}

local function TweenEnded(instance, properties)
	threads[instance] = nil
	for index, property in properties do instance[index] = property end
end

function module.Tween(instances, tweenInfos, properties)
	
	if type(instances) ~= "table" then instances = {instances} end
	if type(tweenInfos[1]) ~= "table" then tweenInfos = {tweenInfos} end
	if type(properties[1]) ~= "table" then properties = {properties} end
	
	for i, instance in instances do
		if threads[instance] ~= nil then task.cancel(threads[instance]) threads[instance] = nil end
		event:FireAllClients(instance, tweenInfos[i], properties[i])
		if tweenInfos[i][5] == true then return end
		local repeatCount = tweenInfos[i][4] or 0
		if repeatCount < 0 then return end
		local delayTime = tweenInfos[i][6] or 0
		local tweenTime = tweenInfos[i][1] or 1
		threads[instance] = task.delay((delayTime + tweenTime) * (repeatCount + 1), TweenEnded, instance, properties[i])
		task.wait((delayTime + tweenTime) * (repeatCount + 1))
	end
	
end

return module
1 Like

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