I'd love some advice on this replication question

In my game, each player owns a plot with a set of nodes. A train is automatically tweened between these nodes using CFrame and Tween Service.

I want tweens to be as smooth as possible for the client and I am perfectly happy for the trains on someones plot to be manipulated by their client. Therefore I decided to set NetworkOwnership to the player for the train part.

However, the issue with CFrame tweening is that the train needs to be anchored. It has a very precise set of nodes to follow and Body Movers wouldn’t really work. Yet as everyone knows - NetworkOwnership does not work with anchored parts.

If anyone has any ideas of a way to achieve this - i’d really appreciate them! Tweening the parts server side is out of the question as in some cases, users can manually control the train which requires an instant response. Or maybe there is a way for me to tween the part locally and somehow efficiently replicate the movement to the other clients?

1 Like

My suggestion is to use anchored parts; Have a copy of each train on the client side. That way, the client will see it smoothly, and you can just fire the client were to tween the trains too.

Hope I could help.

3 Likes

Attempting to do this in the client is futile. Never trust the client, for security purposes (as you may already know).

Not necessarily if this is purely Server > Client motion :thinking:

I didn’t really consider sending the node path to each client as I thought there may be a lag issue if every client is processing the movement of every train on every plot.

2 Likes

Wouldn’t it be more lag if the server was running it? If it’s run by the client, at least one player lagging won’t affect everyone.

3 Likes

I would send data like this:

--Server
local re = xxx--Remote Event
--Make "train" the corresponding of the train
re:FireAllClients(train,moveTo)
--Client
local re = xxx--Remove Event
re.OnClientEvent:Connect(function(train,to)
       --Tween train to new position
end)

Obviously, these is some basic sudo code, but it should work pretty well.
Note: Check the position on the SERVER. Say you reward them 100 coins or something for doing x miles, store the position on the server and send it to the client.

Hope I could help.

2 Likes

Yup that’s likely how i’ll do it :slight_smile:

The money awarding system shouldn’t be too hard as I will just award the user money whenever the server tell all clients too move X train to Y station.

1 Like

This is more of a discussion, looking for pointers more than solutions. More people might be yet to comment as well :slight_smile:

I’d probably do something like this:

  1. Player presses key
  2. Send pressed keycode through an event to the server
  3. Verify input (prevent exploits, invalid actions, etc)
  4. Send event back to all clients (or all clients nearby the object in question) telling them to move the object in the desired direction.

So in your case this translates to the players controlling the train on the client, the action is verified on the server and the actual movement is done on each player’s client. (The tweening)
This is how I did the laser guns for one of my projects too, since giving the projectile NetworkOwnership didn’t work in all cases. Not sure if this would be a good way to handle vehicle movement though, but maybe worth a try.

3 Likes

The problem with this is that there can be delays through remote events. So you might want to first move the object on the client, then have the server verify it.

That’d work, the only issue with that is that players may see the player moving in “illegal” directions if they’re exploiting or lagging before the server verifies the action. (As player movement is replicated from the client to other clients) And unless the player’s ping is high it’s almost unnoticable if you keep it clean.

As is the issue with almost all moving objects. Maybe try using bodyPosition?

1 Like

Handle all train visuals client side. This would make it seem like none of the trains are lagging.

If a player is further away from a train, you can decrease the interval with which the train’s position is incremented.

1 Like

Can’t seem to edit my own post, it’s giving me a 503, but correction:
He wanted to use CFrames specifically.

I tried a combination of body position and body gyro already but they seem to always require some sort of dampening and cannot pro odd instant movement.

They also act weird when manipulated multiple times every second.

You could try bodyVelocity and a bodyGyro, and just always set the velocity to the lookVector of a CFrame pointing towards were it should go.

After combining my own knowledge, some ideas here and private talks with other developers I have come to a final solution I think is right.

To move a train, the server fires a remote event for all clients (apart from the player) within X studs of the players plot so the train moves on those player’s screens.

The server then fires a remote function to the player that owns the plot which tells the train to move between Node A and B. The server waits for this function to finish (for the train to move) before continuing. This solution also stops any issues if the client freeze glitch occurs where a player can hold the X button to freeze all local scripts. If this happens, all other clients will just see the players train waiting at the next station/node

When a train arrives at a station. Another remove event is fired to all clients to make sure the train’s stable position is correct for everyone (e.g. new players)

Wouldn’t that be quite expensive performance wise? It’s a good plan, but is it efficient?

1 Like

That’s what i’ll be testing a LOT after implementing this. Hopefully the fact it only sends data to players within X studs should reduce the load. I will also make train movements as large as possible so the server isn’t constantly sending little increments to the clients.

1 Like