Best way to animate sliding doors for all players on the client side with StreamingEnabled

It was much smoother for all clients… I did a dodgy test which was spawn a million parts till it’s laggy on my devices. It was laggy on the server and smooth on the client.

1 Like

Do you care about possible glitchy interactions between the doors and players? For sliding doors that are physically simulated (collidable, have mass) the preferred way is to use PrismaticConstraints in servo mode. The constraints have built-in support for travel limits, max speed, max force, etc. and because constraints are interpolated locally, they move pretty smoothly. And unlike moving parts directly by changing CFrame, simulated doors can push players without flinging them, and can also transfer velocity to players (not so important for doors, but very important for things like sliding platforms or elevators). Plus, with constraints, your code generally just sets the current target position when something is supposed to move.

Simulated doors that have reasonable forces will stop moving and clamp a player in place if they are caught in the door. CFramed doors will not stop, they will reach their final position as if your character isn’t even there and you may end up getting flung or being trapped overlapping the door parts.

Animating anything collidable with tweens or CFrame lerping directly–without a bodymover or constraint–generally has some problems with things interact with the moving parts.

That said, if you do things locally, there may not be a need to have the doors on the server at all. You could have a proxy part which, when replicated/streamed to the client spawns the door locally only. This is one of the scenarios where you’d need to FireAllClients and make sure all players get the correct initial state when they first join or get the door.

Yes, I prefer the doors not to be glitchy and smooth.

I use to have the doors use prismatic constraints, but I think it’s more optimised to used CFrame doors or tween doors over constraint doors. The doors are part of a train which are controlled by when the player clicks a gui button if they are in the door detector zone.

I suggest trying CollectionService to help squash problems with the doors breaking when the player walks out of the streaming area.

Constraint doors are more predictable when colliding with characters, but they do have other problems. It’s very difficult to sync them up, even just both halves of a double door. You basically have to sync them with mechanical linkages, which is cumbersome. If your use case is like a subway train, where all the doors open and close in sync, you’re probably right to do it with local CFrames.

This may not be useful to you if you go with local doors, but maybe it will help someone else out who finds this thread. What I’m showing here is how I did the doors on Frogge’s upcoming spaceship map. Because of the issue I mentioned of not being able to sync the left and right doors using two servo-enabled prismatics, what I did is leave the doors’ horizontal sliding prismatics unpowered, and instead there is a single vertical servo prismatic that acts like a piston and connects to the doors with RodConstraints. The result is that it’s always perfectly synched. I also like the natural sinusoid easing that results from the geometry of this setup.

As you can probably gather from the test place video here, I tried pretty much every way of doing sliding double doors imaginable :slight_smile:

I don’t really mind if it collides or not, it’s only going to push the character out of the way. If I wanted to I could use some sort of detection system to detect if there’s something in the way of the door and make the door open itself if it detects something.

Using lerp just feels a lot cleaner to me, plus it’s probably more performant since no physics. Plus using constrains, I can’t really make the doors not collide with the trains walls and things while being able to collide with players, I know I could use collision constraints or collision groups, but that just feels messy to me.

My best bet to me, is probably to go for the client side CFrame thing. I will let you know what the best way is for my tests.

You know you can also just connect the doors to the body of the train with Motor6D and animate them locally by setting the Motor6D.Transform to be your linear displacement. This still has no physics simulation, since motors are rigid welds during simulation, but it avoids having to have code to calculate the door CFrames in local space of the vehicle. When parts are welded together, you don’t need collision groups or NoCollisionConstraints, and you don’t have to have everything anchored. It’s very clean and also hyperoptimized since it’s how avatars animate.

I am using motor6Ds to move it, but I move it by the C1 property and not the transform property, do you mind sending a basic example of the transform way?

Does the transform property animate automatically or is it like CFrame or?

I can send a basic model of the train doors later if you like!

Motor6D.Transform is also just a CFrame, it’s what the animator uses, and it’s more optimized for being set every frame and will never replicate from server to client (C0 and C1 do). It also avoids the warning spam you get if you try to animate C0 or C1, which is there to remind you that this results in more calculation being done behind the scenes than setting Transform.

Setting Transform to have a translation (same as position) will work the same as if you adjusted C0, and will move in exactly the opposite direction as the same translation applied to C1. This is because the multiplication order for Motor6D is C0 x Transform x C1:Inverse()

So you might have to swap direction, but otherwise it will work the same as animating C0 or C1, provided you don’t need the server to client replication (which for local animation you ofc don’t).

So is setting the transform CFrame better than setting the C1 CFrame?

And so if I change the CFrame for one of these properties on the client it would show for everyone or only the client that changed it?

It’s better than setting C1, yes. But it does not replicate in either direction, so you have to set it on each client. This is much easier to do now with Scripts that have RunContext of Client, rather than LocalScripts.

So does the runcontext script mean that a player can update things on the server from the client?

I’m honestly impressed at the amount of misinformation here.

Moving any motor or force, server or clientside, will be as smooth as heartbeat.

There is this thing called “prediction”, the client will keep moving the part even if the server is not updating as fast. It will rollback if the server is completely frozen.

Roblox has no prediction and rollback mechanism, it never has. Simulated bodies have client-side interpolation between their previous and current state, smoothing out the 3X framerate difference between replication and rendering, but things don’t normally rubber-band (roll back); when parts reach their latest known state on the client, they’ll simply stop changing until they get another update from the server (unless there is also client code updating them). There are a few games on Roblox that have implemented their own prediction and rollback systems, but I can count them on one hand, it’s not a built-in Roblox engine feature.

Client-side interpolation is only done for unanchored parts that are being moved by the physics simulation. They have to be driven by physics forces and velocity, which is true if you move something using a body mover, or constraint (AlignPosition, AlignOrientation, Hinge, Prismatic, etc). If you animate something on the server by setting its part.CFrame, setting pivot, Motor C0, C1, etc. directly from Lua, you will not have interpolation and client-side updates will be at the replication rate (~20 FPS) and will visibly show any timing irregularities in your server-to-client packet timing. This is why a lot of enviromental stuff that’s moving in Roblox games looks like it’s going at a low framerate, it’s being CFramed server-side.

Which is why I said CFraming on the server side is bad, use a method that interpolates.

How would I do that? I don’t really understand.

Or lets do this, I want the doors to open with CFrame.

How would you do this?
Once a player presses a GUI button, it’ll fire a server event that will FireAllClients that’ll open or close the door?