Why is tweening C0 / C1 Values in welds so glitchy?

Hey! I am tweening the C0 value of a weld in my game and I am doing this through the client. Every time it reaches the end goal of the tween and goes onto the next one, and just in general throughout the tween, it is really really glitchy.

It does not do this if I use WeldConstraints but I can’t use them as I am tweening 2 other parts that are all connected to other tweened parts.

When I try it in game, it is no where near as bad, but still noticeable and not as smooth as I would of liked it.

Can anyone help?

why dont you use CFrame? it is easier as you just have to change the rotation of it every frame .

You can just do:

local SpinPerSec = 180
Runservice.Renderstep: Connect(function(delta)
weld.CFrame *= Cframe.Angle(math.rad(SpinPerSec * delta),0,0)
end)

Because I am using Welds. Can I still use CFrame?

Yes . I am currently not in studio but Weld should have CFrame value like C0 and C1

btw plz take note that the script i provide might have spelling error

These are the properties the weld has:

image

i suppose it is C0 . C0 is a CFrameValue

That is what I am tweening. The C0 value.

local tweenGoals = {C0 = CFrame.new(partPos) * CFrame.Angles(math.rad(rotationAngel), 0, 0)}

How were you tweening it without C0 and C1? That is the only way to change the offset of a Weld

Also, where is the code?

can you share some more code rather than that one line

I am tweening C0 and C1 now. If I used wel constraints, I would tween the CFrame valkye, but I cannot use them.

local tweenGoals1 = {C0 = CFrame.new(partPos) * CFrame.Angles(math.rad(90), 0, 0)}
local tweenGoals2 = {C0 = CFrame.new(partPos) * CFrame.Angles(math.rad(180), 0, 0)}
local tweenGoals3 = {C0 = CFrame.new(partPos) * CFrame.Angles(math.rad(-90), 0, 0)}
local tweenGoals4 = {C0 = CFrame.new(partPos) * CFrame.Angles(math.rad(0), 0, 0)}

DLocalTween.DLocalTween(bigPlatePart.SpinningWeld, tweenInfo, tweenGoals1)
wait(animationTime)
DLocalTween.DLocalTween(bigPlatePart.SpinningWeld, tweenInfo, tweenGoals2)
wait(animationTime)
DLocalTween.DLocalTween(bigPlatePart.SpinningWeld, tweenInfo, tweenGoals3)
wait(animationTime)
DLocalTween.DLocalTween(bigPlatePart.SpinningWeld, tweenInfo, tweenGoals4)
wait(animationTime)

Do you need more code?

I would use lerp

local urweld = ...

game:GetService("RunService").Heartbeat:Connect(function(dt)
urweld.C0 = urweld.C0:Lerp(CFrame.Angles(0, math.fmod(os.clock(), math.pi * 2), 0), dt * 10)
end)
1 Like

This seems to be an issue with client-server replication try using; BasePart:SetNetworkOwnership(Player?). Try setting the player argument to the player sitting there and that might work.

1 Like

You should use Tween.Completed rather that wait (especially with wait, task.wait might lead to a smoother result)

However, as @Empereans pointed out, it is better to use lerp instead of tweens

I would use Tween.Completed but i cannot due to my local tweening system.

I will try out the lerp system in the next couple of hours and see if that works, I have always wanted to use lerp but never really understood how I would make it come to a smooth stop etc.

Hey!
I tried this and it does work yes, and looks much better!

Do you know how to locally lerp and sync up all the clients? If not don’t worry. Also do you know how I would smoothly stop the lerp?

One thing I like doing is something like this

local RPS = 1 -- Rotations per second

Runservice.RenderStepped:Conncect(function()
   Weld.CO = CFrame.new(partPos) * CFrame.Angles(math.pi*2*RPS*tick(),0,0)
end)
-- math.pi*2 is the equivalent of 360°, but in radians

This updates the position of the part every frame (similarly to how Empeareans did it, but without lerp), but my way and, by using tick(). tick() returns the unix time (in UTC), and is about the same for everyone, HOWEVER, tick() apparently has a different behaviour depending on the client’s platform? Idk, anyway, you can use another way of getting the unix time in UTC, I made a module just for that: Reliable time module (alternative to tick())

Using tick(), or my module, can lead to some differences between clients, if their system’s clock isn’t synced perfectly. In your case, it might be fine, but if it isn’t it is possible to get the time from the server to synchronize the client’s clock (I have an updated version of my module that those this synchronization when the client joins, and I am able to get the time synced really well)

1 Like

Put the same script but in a localscript, if you wanna stop the lerp then

local urweld = ...

local con = game:GetService("RunService").Heartbeat:Connect(function(dt)
urweld.C0 = urweld.C0:Lerp(CFrame.Angles(0, math.fmod(os.clock(), math.pi * 2), 0), dt * 10)
end)

task.wait(3)
con:Disconnect()

the part looks like it’s anchored so that wouldn’t work. if it was unanchored the property wouldn’t replicate, and even if it did, the client has network ownership while the server is trying to set the value so it would just be even more jittery

Then why not set the networkownership to the server itself?